{"record":{"id":"a6e60f4acd49b105","repo":"t8y2/dbx","slug":"unsupported-object-type-objecttype-a6e60f","errorCode":null,"errorMessage":"Unsupported object type: \" + objectType","messagePattern":"Unsupported object type: \" \\+ objectType","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agents/drivers/oscar/src/main/java/com/dbx/agent/oscar/OscarAgent.java","lineNumber":79,"sourceCode":"     *   <li>VIEW → ALL_VIEWS.TEXT（返回完整 SELECT 语句）</li>\n     *   <li>PROCEDURE/FUNCTION/PACKAGE/PACKAGE_BODY/TYPE/TYPE_BODY → ALL_SOURCE.TEXT 按 LINE 排序拼接</li>\n     *   <li>TRIGGER → ALL_TRIGGERS.TRIGGER_BODY</li>\n     *   <li>SEQUENCE → 由 ALL_SEQUENCES 元数据重建 CREATE SEQUENCE 语句</li>\n     *   <li>MATERIALIZED_VIEW → 神通无 ALL_MVIEWS，返回空源码且不可编辑</li>\n     * </ul>\n     */\n    @Override\n    public ObjectSource getObjectSource(String schema, String name, String objectType) {\n        String type = objectType == null ? \"\" : objectType.trim().toUpperCase(Locale.ROOT);\n        return unchecked(() -> {\n            String source = switch (type) {\n                case \"VIEW\" -> readViewSource(schema, name);\n                case \"PROCEDURE\", \"FUNCTION\", \"PACKAGE\", \"PACKAGE_BODY\", \"TYPE\", \"TYPE_BODY\" -> readSourceText(schema, name, type);\n                case \"TRIGGER\" -> readTriggerSource(schema, name);\n                case \"SEQUENCE\" -> readSequenceSource(schema, name);\n                // 神通 v7 无物化视图系统视图（ALL_MVIEWS 不存在）；返回空源码，标记不可编辑，避免 UI 误判为可改。\n                case \"MATERIALIZED_VIEW\" -> \"\";\n                default -> throw new IllegalArgumentException(\"Unsupported object type: \" + objectType);\n            };\n            boolean editable = !\"MATERIALIZED_VIEW\".equals(type);\n            return new ObjectSource(name, objectType, schema, source, editable);\n        });\n    }\n\n    private String readViewSource(String schema, String name) throws Exception {\n        // ALL_VIEWS.TEXT 已包含完整视图定义（神通实测返回带 schema 限定的 SELECT 语句）。\n        String sql = \"SELECT TEXT FROM ALL_VIEWS WHERE OWNER = ? AND VIEW_NAME = ?\";\n        return scalarText(sql, schema, name);\n    }\n\n    private String readSourceText(String schema, String name, String type) throws Exception {\n        // ALL_SOURCE 按 LINE 存储过程/函数/包/类型的源码行，需按 LINE 排序拼接。\n        // 神通与 Oracle 的关键差异（实测 v7.0.8）：function 也以 TYPE='PROCEDURE' 存储（不区分 FUNCTION），\n        // 包体随包一起存为 TYPE='PACKAGE'，类型体随类型存为 TYPE='TYPE'。故按 objectType 归并到实际 TYPE 值。\n        String sourceType = switch (type) {\n            case \"PROCEDURE\", \"FUNCTION\" -> \"PROCEDURE\";","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/oscar/src/main/java/com/dbx/agent/oscar/OscarAgent.java#L61-L97","documentation":"OscarAgent.getObjectSource supports VIEW, PROCEDURE, FUNCTION, PACKAGE, PACKAGE_BODY, TYPE, TYPE_BODY, TRIGGER and SEQUENCE. The Shentong (神通) v7 catalog has no ALL_MVIEWS view, so MATERIALIZED_VIEW returns empty source (marked non-editable), and every other type throws IllegalArgumentException because no source-reading path exists for it.","triggerScenarios":"Calling getObjectSource(schema, name, objectType) on OscarAgent with a type outside the switch — e.g. \"SYNONYM\", \"DBLINK\", \"INDEX\", a misspelled type, or an unnormalized label containing spaces/lowercase.","commonSituations":"A generic database explorer iterates all catalog object kinds and requests source for each; new Oscar object types appear in a version the driver predates; UI passes raw user-entered type strings without normalization.","solutions":["Restrict source requests to the supported set (VIEW, PROCEDURE, FUNCTION, PACKAGE, PACKAGE_BODY, TYPE, TYPE_BODY, TRIGGER, SEQUENCE).","Normalize the type string (trim/uppercase, spaces to underscores) and handle MATERIALIZED_VIEW as empty/non-editable as the driver does.","For unsupported kinds, skip source retrieval in the caller and display a 'source not available' state instead of calling the API."],"exampleFix":"// before\nvar src = agent.getObjectSource(schema, name, \"SYNONYM\"); // throws\n// after\nif (Set.of(\"VIEW\",\"PROCEDURE\",\"FUNCTION\",\"PACKAGE\",\"PACKAGE_BODY\",\"TYPE\",\"TYPE_BODY\",\"TRIGGER\",\"SEQUENCE\",\"MATERIALIZED_VIEW\")\n        .contains(type.toUpperCase(Locale.ROOT))) {\n    var src = agent.getObjectSource(schema, name, type.toUpperCase(Locale.ROOT));\n}","handlingStrategy":"validation","validationCode":"Set<String> SUPPORTED = Set.of(\"VIEW\",\"PROCEDURE\",\"FUNCTION\",\"PACKAGE\",\"PACKAGE_BODY\",\"TYPE\",\"TYPE_BODY\",\"TRIGGER\",\"SEQUENCE\",\"MATERIALIZED_VIEW\");\nif (objectType == null || !SUPPORTED.contains(objectType.toUpperCase(Locale.ROOT))) {\n    // skip source retrieval / show \"source unavailable\"\n}","typeGuard":"boolean oscarSupportsSource(String t) {\n    return t != null && Set.of(\"VIEW\",\"PROCEDURE\",\"FUNCTION\",\"PACKAGE\",\"PACKAGE_BODY\",\"TYPE\",\"TYPE_BODY\",\"TRIGGER\",\"SEQUENCE\",\"MATERIALIZED_VIEW\")\n        .contains(t.trim().toUpperCase(Locale.ROOT));\n}","tryCatchPattern":"try {\n    source = agent.getObjectSource(schema, name, type);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unsupported object type\")) {\n        source = \"\"; // render as non-editable/no source\n    } else throw e;\n}","preventionTips":["Gate the 'view source' action on the supported-type set in the UI layer.","Normalize type strings before calling; treat MATERIALIZED_VIEW as empty/non-editable like the driver does.","For unsupported kinds, query Oscar catalog views directly instead of getObjectSource."],"tags":["oscar","shentong","source-retrieval","unsupported-type"],"backgroundTag":"unsupported-object-type","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}