Skip to content

[fix](jdbc) Resolve SQL Server user-defined alias types by JDBC type code - #67916

Merged
morningman merged 3 commits into
apache:masterfrom
morningman:wt-sqlserver
Sep 14, 2026
Merged

morningman merged 3 commits into
apache:masterfrom
morningman:wt-sqlserver

Conversation

@morningman

@morningman morningman commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #67793

Related PR: none

Problem Summary:

Columns declared with a SQL Server user-defined alias type (CREATE TYPE dbo.customtexttype FROM varchar(50)) are mapped to UNSUPPORTED_TYPE by the JDBC catalog, so SELECT * on such a table fails with

type UNSUPPORTED is unsupported for Nereids

JdbcSQLServerClient.jdbcTypeToDoris() (and its counterpart JdbcSQLServerConnectorClient.jdbcTypeToConnectorType() in fe-connector-jdbc) dispatches only on TYPE_NAME. For an alias type, DatabaseMetaData.getColumns() reports the alias name (customtexttype) as TYPE_NAME, so the name never matches and the default branch returns UNSUPPORTED. The same result set however still carries the base type in DATA_TYPE (java.sql.Types.VARCHAR), COLUMN_SIZE (50) and DECIMAL_DIGITS.

This PR keeps the name-based switch as the primary mapping (it carries SQL Server specific choices such as tinyint -> SMALLINT and money -> DECIMAL(19,4)) and, only when the name is not recognised, resolves the column by its standard java.sql.Types code. The fallback mirrors the name-based mapping and is applied in both implementations:

  • fe/fe-core/.../jdbc/client/JdbcSQLServerClient.java
  • fe/fe-connector/fe-connector-jdbc/.../JdbcSQLServerConnectorClient.java

Scope of the fallback (verified against the mssql-jdbc DataTypeFilter that post-processes getColumns()):

base type of the alias DATA_TYPE Doris type
bit BIT BOOLEAN
tinyint / smallint TINYINT / SMALLINT SMALLINT
int / bigint INTEGER / BIGINT INT / BIGINT
real REAL FLOAT
float DOUBLE (driver maps ODBC FLOAT to DOUBLE) DOUBLE
decimal / numeric / money / smallmoney DECIMAL / NUMERIC with the base precision and scale DECIMALV3(p, s), string when p > 38
date DATE DATEV2
datetime / datetime2 / smalldatetime TIMESTAMP, scale capped at 6 DATETIMEV2(scale)
char / varchar / text / nchar / nvarchar / ntext / time / uniqueidentifier / sysname CHAR / VARCHAR / LONGVARCHAR / NCHAR / NVARCHAR / LONGNVARCHAR / TIME STRING

The name-based path strips the IDENTITY decoration a column is reported with (int identity, decimal() identity, numeric(18, 0) identity, decimal(18,0) IDENTITY(1,1)) only when the name has that form for one of the base types IDENTITY is allowed on and DATA_TYPE is that base type's code. Any other name is matched as it is: SQL Server allows an alias to be named with spaces or parentheses (CREATE TYPE dbo.[int alias] FROM varchar(50), reported as TYPE_NAME = int alias, DATA_TYPE = VARCHAR), and cutting the name at the first space or parenthesis, as both clients did, turned such an alias into the system type its name starts with (an INT column for a varchar alias). An alias cannot share a system type's name outright (CREATE TYPE dbo.[int] ... is rejected by SQL Server), so an unrecognised name is an alias and goes to the code fallback.

Deliberately not resolved by the fallback:

  • Binary codes (BINARY, VARBINARY, LONGVARBINARY): mssql-jdbc reports CLR user-defined types (geometry, geography, hierarchyid, ...) as VARBINARY too, so an alias over varbinary cannot be told apart from an unsupported CLR type by the type code alone. They stay UNSUPPORTED.
  • Vendor specific codes (sql_variant, datetimeoffset aliases): stay UNSUPPORTED.
  • A consequence of the two rules above: an alias whose name starts with a binary type name and whose base type is binary too (CREATE TYPE dbo.[varbinary alias] FROM varbinary(20)) is UNSUPPORTED as well. Before this PR its name was cut to varbinary and the column happened to be readable; now the name is not a system type name and the binary code is not resolved.
  • xml, sql_variant, geometry, geography, hierarchyid, json, vector are now listed explicitly as unsupported system types so that the fallback never changes their existing behavior (xml would otherwise be reported as LONGNVARCHAR).

The BE side needs no change: the scanner reads values by the Doris column type (getObject() / getBigDecimal()), and the driver returns the Java object of the base type for alias columns.

Release note

Fix SQL Server JDBC catalog mapping columns of user-defined alias types (CREATE TYPE ... FROM base_type) to UNSUPPORTED_TYPE; they are now resolved to the Doris type of their base type. Aliases over binary, varbinary, image, datetimeoffset and sql_variant remain UNSUPPORTED.

Check List (For Author)

  • Test

    • Regression test

    • Unit Test

    • Manual test (add detailed scripts or steps below)

    • No need to test or manual test. Explain why:

      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
    • Unit tests: new JdbcSQLServerClientTest (fe-core) and extended JdbcSQLServerConnectorClientTest (fe-connector-jdbc) cover alias columns for every base type family, prove that unknown / CLR / vendor-specific types stay UNSUPPORTED, that the name-based mapping still takes precedence, and that alias names which start with a system type name (int alias, decimal(18,0) identity, int identity over varchar) are resolved by their code while the real IDENTITY forms of every driver version still resolve by name.

    • Regression test: the SQL Server docker fixture now creates aliases over every supported base type family (dbo.test_alias_type, incl. sysname), an alias typed IDENTITY column (dbo.test_alias_identity) and a negative table (dbo.test_alias_unsupported: aliases over binary types / datetimeoffset / sql_variant plus xml / geometry / hierarchyid), and dbo.test_alias_name with aliases named [int alias], [decimal(18,0) identity] and [int identity] next to a real IDENTITY column. test_sqlserver_jdbc_catalog asserts DESC and SELECT * on the positive tables, and for the negative table that the columns are reported as UNSUPPORTED_TYPE, that the other columns stay readable, that SELECT * still fails, and that enable.mapping.varbinary does not change the alias behavior. Verified end to end on a local 1 FE + 1 BE cluster built from this branch against the SQL Server 2022 docker image: the suite passes and the real output of the nine new blocks is identical to the committed .out. The suite is in group p2, which the External Regression pipeline excludes (excludeGroups = "p1,p2"), so CI does not execute it; the local run above is the only execution. Note that the JDBC catalog runs through the fe-connector-jdbc plugin, so the regression test exercises JdbcSQLServerConnectorClient; the fe-core JdbcSQLServerClient (used by the streaming / CDC path) is covered by its unit test, and the two mappings are equivalent case by case.

    • Metadata evidence: sp_columns_100 (ODBC v3, what mssql-jdbc calls from getColumns()) on SQL Server 2022 reports alias columns with TYPE_NAME = alias name and DATA_TYPE = the base type code: varchar 12, nvarchar -9, int 4, bigint -5, tinyint -6, bit -7, decimal and money 3 (money with precision 19 / scale 4), float 6 (the driver maps it to DOUBLE), date 91, datetime/datetime2/smalldatetime 93 with the base scale, time -154 (mapped to TIME), uniqueidentifier -11 (mapped to CHAR), datetimeoffset -155, binary/varbinary/image -2/-3/-4, sql_variant -150, xml -152 (mapped to LONGNVARCHAR), geometry/geography/hierarchyid -151 (mapped to VARBINARY).

  • Behavior changed:

    • Yes. SQL Server columns of user-defined alias types (and sysname) are now readable through the JDBC catalog instead of being reported as UNSUPPORTED_TYPE. An alias whose name starts with a system type name ([int alias]) is no longer mistaken for that system type: it is resolved by its base type, or reported as UNSUPPORTED when the base type is one of the five families above. Columns of other SQL Server types keep their previous mapping.
  • Does this need documentation?

    • No.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

🤖 Generated with Claude Code

…code

Columns declared with a SQL Server alias type (CREATE TYPE ... FROM
base_type) were mapped to UNSUPPORTED by the JDBC catalog, because
DatabaseMetaData.getColumns() reports the alias name as TYPE_NAME and the
SQL Server client only dispatched on that name. SELECT * on such a table
then failed with "type UNSUPPORTED is unsupported for Nereids".

The same result set still carries the base type in DATA_TYPE, COLUMN_SIZE
and DECIMAL_DIGITS. Keep the name based mapping as the primary path and,
only for names that are not SQL Server system types, resolve the column by
its standard java.sql.Types code with a mapping that mirrors the name
based one. Binary and vendor specific codes stay unsupported because
mssql-jdbc reports CLR user-defined types as VARBINARY too. Applied to
both JdbcSQLServerClient (fe-core) and JdbcSQLServerConnectorClient
(fe-connector-jdbc).

Unit tests cover alias columns of every base type family and the types
that must remain unsupported. The SQL Server docker fixture gains alias
types and a test_alias_type table which test_sqlserver_jdbc_catalog now
checks with DESC and SELECT *.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@morningman

Copy link
Copy Markdown
Contributor Author

Local pipeline review — ✅ PASS

schema: doris-repo-review/v1
status: PASS
pr: apache/doris#67916
commit: 39de21240f76b53ba3a5451c6a3f5070518205c3
base: 2573820600eb178150a35710a94fd58b478df96d
reviewed_at: 2026-09-14T00:15+08:00
reviewer: morningman
model: claude-opus-5
effort: max
findings: {blocker: 0, major: 0, minor: 2, nit: 2}
rounds: 1
converged: true

Notes for maintainers

  • fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcSQLServerClient.java:128 — the binary carve-out is wider than its reason: mssql-jdbc's DataTypeFilter rewrites only ODBC -151 (CLR UDT) to VARBINARY, so aliases over datetimeoffset (-155), binary (-2) and image (-4) are unambiguous and could mirror the name path (STRING / VARBINARY) instead of staying UNSUPPORTED; SELECT * still fails for such tables. Same in JdbcSQLServerConnectorClient. (Minor)
  • docker/thirdparties/docker-compose/sqlserver/init/03-create-table.sql:291 — 7 fallback families (smallint, real, numeric, smallmoney, datetime, smalldatetime, char/nchar/text/ntext, uniqueidentifier), sysname, alias+IDENTITY and the UNSUPPORTED-alias case are unit-tested only; the regression also exercises only the connector plugin path (fe-core JdbcSQLServerClient is reached via streaming/CDC jobs alone). (Minor)
  • fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcSQLServerClient.java:41 — fe-core matches TYPE_NAME case-sensitively while the connector lowercases; with the new explicit list a mixed-case alias such as dbo.JSON FROM nvarchar(max) resolves to STRING in one and UNSUPPORTED in the other. (Nit)
  • fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcSQLServerClient.java:159 — decimal/datetime rules are duplicated between the two switches; fe-core hard-codes 6 although JdbcClient.JDBC_DATETIME_SCALE exists. (Nit)
  • Verified against mssql-jdbc 12.10.2 sources: CLR UDTs arrive as VARBINARY, sysname is the only system type whose mapping changes, and the BE scanner needs nothing because it reads by Doris type and TDS carries the base type for alias columns.

Reviewed locally with the doris-repo-review pipeline. Repository policy may accept this receipt for the matching commit; it is not a human Apache approval.

…rted ones end to end

Extend the SQL Server docker fixture so that test_sqlserver_jdbc_catalog
exercises an alias over every supported base type family (character,
integer, floating point, decimal and money, date and time, uniqueidentifier
and sysname), an alias typed IDENTITY column, and a negative table whose
aliases over binary types, datetimeoffset and sql_variant as well as the
xml / CLR system types must stay UNSUPPORTED while the remaining columns
are still readable and SELECT * keeps failing on them. The last table is
also described through a catalog with enable.mapping.varbinary to show
that the option does not change the alias behavior.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16949 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit e3d911b29ffe26388794f877a33190d1f3d45b0a, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17591	3058	3050	3050
q2	2069	255	221	221
q3	10267	856	515	515
q4	4680	246	203	203
q5	7674	558	389	389
q6	136	118	96	96
q7	524	494	399	399
q8	9250	963	943	943
q9	3431	2434	2412	2412
q10	6511	861	753	753
q11	395	203	183	183
q12	648	259	197	197
q13	18112	1534	1170	1170
q14	159	156	134	134
q15	q16	442	405	375	375
q17	1361	918	850	850
q18	3074	2251	2228	2228
q19	1269	857	753	753
q20	369	286	201	201
q21	5628	1645	1847	1645
q22	336	275	232	232
Total cold run time: 93926 ms
Total hot run time: 16949 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3437	3341	3343	3341
q2	508	397	369	369
q3	2267	2317	2160	2160
q4	1189	1180	896	896
q5	2180	2130	2107	2107
q6	170	122	86	86
q7	1020	947	853	853
q8	1592	1394	1399	1394
q9	3153	3125	3124	3124
q10	1854	1818	1605	1605
q11	355	270	250	250
q12	460	428	349	349
q13	1478	1532	1168	1168
q14	166	177	157	157
q15	q16	391	395	366	366
q17	3575	3313	3238	3238
q18	4818	4474	4756	4474
q19	875	919	908	908
q20	1024	977	862	862
q21	3871	3234	3230	3230
q22	400	348	326	326
Total cold run time: 34783 ms
Total hot run time: 31263 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 82129 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit e3d911b29ffe26388794f877a33190d1f3d45b0a, data reload: false

query5	4237	409	335	335
query6	393	133	121	121
query7	4952	390	218	218
query8	293	123	119	119
query9	8725	2893	2892	2892
query10	397	230	176	176
query11	5381	1040	971	971
query12	111	71	70	70
query13	1190	414	313	313
query14	6058	2198	2088	2088
query14_1	1971	1950	1959	1950
query15	175	124	108	108
query16	896	363	333	333
query17	790	433	350	350
query18	2319	315	223	223
query19	165	131	102	102
query20	77	70	73	70
query21	198	103	86	86
query22	5414	5302	5343	5302
query23	6633	6345	6027	6027
query23_1	6176	6086	6153	6086
query24	7278	1111	765	765
query24_1	741	761	767	761
query25	411	279	236	236
query26	1212	221	124	124
query27	2804	424	248	248
query28	4692	1484	1506	1484
query29	928	423	334	334
query30	249	161	130	130
query31	820	405	324	324
query32	128	68	70	68
query33	458	210	168	168
query34	973	850	464	464
query35	393	406	334	334
query36	565	574	538	538
query37	116	85	69	69
query38	993	849	817	817
query39	492	475	485	475
query39_1	451	447	461	447
query40	199	90	74	74
query41	53	51	51	51
query42	78	70	72	70
query43	242	239	208	208
query44	984	535	546	535
query45	109	107	103	103
query46	825	864	528	528
query47	753	763	706	706
query48	315	323	216	216
query49	560	258	195	195
query50	743	263	203	203
query51	8206	8242	8276	8242
query52	70	70	59	59
query53	193	195	154	154
query54	216	166	170	166
query55	76	64	58	58
query56	208	194	176	176
query57	730	676	640	640
query58	201	165	156	156
query59	1243	1228	1120	1120
query60	249	193	181	181
query61	125	131	121	121
query62	364	208	181	181
query63	179	150	143	143
query64	2943	722	591	591
query65	1639	1653	1609	1609
query66	1876	273	208	208
query67	10274	9669	9731	9669
query68	3044	1190	729	729
query69	356	226	195	195
query70	662	639	644	639
query71	262	172	149	149
query72	2254	1640	1514	1514
query73	673	611	312	312
query74	1987	1217	1151	1151
query75	1174	1104	955	955
query76	2374	721	510	510
query77	254	264	214	214
query78	3971	3683	3283	3283
query79	2729	802	561	561
query80	1578	317	275	275
query81	571	155	137	137
query82	668	130	102	102
query83	279	202	193	193
query84	327	109	90	90
query85	832	345	278	278
query86	473	180	170	170
query87	1009	975	898	898
query88	2981	2159	2123	2123
query89	279	197	171	171
query90	2026	132	133	132
query91	131	120	103	103
query92	90	69	72	69
query93	1854	1097	749	749
query94	636	255	226	226
query95	523	258	229	229
query96	828	626	271	271
query97	1039	1041	1002	1002
query98	184	134	132	132
query99	424	343	308	308
Total cold run time: 179802 ms
Total hot run time: 82129 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 14.54 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit e3d911b29ffe26388794f877a33190d1f3d45b0a, data reload: false

query1	0.01	0.01	0.00
query2	0.08	0.04	0.04
query3	0.26	0.11	0.10
query4	1.61	0.10	0.09
query5	0.18	0.16	0.16
query6	1.25	0.70	0.69
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.29	0.21	0.21
query10	0.35	0.34	0.34
query11	0.17	0.12	0.11
query12	0.15	0.12	0.12
query13	0.30	0.31	0.32
query14	0.45	0.46	0.46
query15	0.36	0.36	0.35
query16	0.23	0.23	0.22
query17	0.70	0.67	0.68
query18	0.18	0.16	0.16
query19	1.23	1.05	1.08
query20	0.02	0.00	0.01
query21	15.49	0.17	0.12
query22	5.08	0.05	0.05
query23	16.17	0.25	0.10
query24	2.96	0.32	0.25
query25	0.10	0.04	0.04
query26	0.84	0.16	0.12
query27	0.03	0.04	0.03
query28	3.70	0.57	0.29
query29	12.43	3.16	2.58
query30	0.26	0.11	0.12
query31	2.75	0.37	0.17
query32	3.53	0.32	0.23
query33	1.50	1.35	1.47
query34	15.38	2.15	1.76
query35	1.76	1.76	1.73
query36	0.50	0.31	0.28
query37	0.07	0.04	0.03
query38	0.04	0.04	0.03
query39	0.04	0.02	0.03
query40	0.13	0.08	0.08
query41	0.08	0.03	0.02
query42	0.03	0.02	0.02
query43	0.03	0.02	0.03
Total cold run time: 90.81 s
Total hot run time: 14.54 s

airborne12 added a commit to airborne12/apache-doris that referenced this pull request Sep 13, 2026
Issue Number: close apache#67916

Related PR: apache#67917

Problem Summary:
The max_ngram_diff creation limit incorrectly changed analyzer identity, allowing equivalent custom analyzers to bypass duplicate-index detection. FE also accepted non-ASCII digits that the BE integer parser rejects.

Exclude max_ngram_diff from ngram tokenizer identity and require its value to use ASCII integer syntax.

Release note:
None

Validation:
- ./run-fe-ut.sh --run org.apache.doris.analysis.invertedindex.AnalyzerIdentityBuilderTest,org.apache.doris.indexpolicy.PolicyValidatorTests (27 tests passed)
- FE Checkstyle passed as part of the targeted test run

Behavior changed:
Equivalent ngram analyzers now share an identity regardless of max_ngram_diff, and FE rejects non-ASCII max_ngram_diff values.

Documentation impact:
None
airborne12 added a commit to airborne12/apache-doris that referenced this pull request Sep 13, 2026
### What problem does this PR solve?

Issue Number: close apache#67916

Related PR: apache#67917

Problem Summary:

An arbitrarily large max_ngram_diff could multiply token output without a hard fan-out bound, and the deterministic regression assertion was not stored as a runner-generated golden.

Cap max_ngram_diff at 255 consistently in FE and BE, cover the accepted and rejected boundaries, and replace the manual token-list assertion with a named golden query generated by the regression runner.

### Release note

The max_ngram_diff tokenizer setting accepts values from 0 through 255.

### Check List (For Author)

- Test
    - [x] Regression test
    - [x] Unit Test
    - [x] Manual test
- Behavior changed:
    - [ ] No.
    - [x] Yes. max_ngram_diff values above 255 are rejected to bound per-position token fan-out.
- Does this need documentation?
    - [ ] No.
    - [x] Yes. Document the supported max_ngram_diff range.

Validation:

- ./build.sh --be -j8 (ASAN, Java extensions, build hygiene, and glibc compatibility)
- ./build.sh --fe -j8
- NGramTokenizerTest: 16/16 passed
- AnalyzerIdentityBuilderTest and PolicyValidatorTests: 29/29 passed
- test_ngram_max_diff_custom_analyzer: runner-generated golden and clean comparison passed on an isolated local FE/BE
- clang-format 16, clang-tidy, and Checkstyle passed
@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 0.00% (0/18) 🎉
Increment coverage report
Complete coverage report

morningman pushed a commit to morningman/doris-skills that referenced this pull request Sep 14, 2026
…judge regressions against the merge base

Review of apache#12 raised two gaps in the regression rule:

1. doc-templates.md scoped the Major floor to a list of categories while
   verify-review-docs.py floored every `Regression: yes` regardless, so a
   reviewer following the documented exception for an observability change
   produced a document the verifier rejected.
2. The regression evidence was `git show $BASE_SHA:<path>`, the target-branch
   tip. When the PR branch is behind that tip, a fix that landed on the target
   branch after the PR branched off is absent at HEAD without the PR having
   removed anything, and the rule would have turned it into a Major regression.

Category-aware floor:

- Every finding carries a mandatory `Category` / `类别` line from a closed
  vocabulary: functional-bug, functional-loss, data-error, resource-leak,
  performance, observability, test-coverage, wording, maintainability. The
  verifier rejects an unknown value (a typo must not escape the floor),
  accepts one parenthetical domain note after the class, resolves ZH aliases
  (功能性bug, 功能性缺失, 资源泄漏, 性能), and requires EN and ZH to agree.
- A regression in the first five categories is at least Major. A regression
  in the other four may stay Minor/Nit only with a `Severity rationale`
  paragraph, which the verifier now checks for.
- The JSON result adds `floored_regressions`. post-pass-comment.sh refuses on
  a floored regression (it can only appear if the two scripts disagree) and
  refuses to post when a non-floored regression would go undisclosed: the
  receipt needs at least one note, and SKILL.md / pr-comment-format.md say
  every such finding is named there first.

Merge base:

- Regression evidence is `git show $MERGE_BASE:<path>` in SKILL.md (premise
  checks, step 6), prompts.md (preamble, D1, E), the ledger skeletons and the
  templates; `{MERGE_BASE}` joins the prompt placeholders. `BASE_SHA` keeps
  its two jobs: the diff range and the commit the receipt binds to.
- prepare-review-context.sh records `TARGET_AHEAD` (target-branch commits
  since the merge base) in meta.env and prints it when non-zero.
- Two new common traps: filing a real behaviour change under a soft category,
  and comparing against the target-branch tip.

Tests: verify/repo-review covers each floored category, the rationale
requirement and acceptance for each non-floored category, the parenthetical
note, spelling variants, missing / unknown / disagreeing categories, and the
poster's disclosure gate. Suite: 63 PASS (was 47). Also replayed against the
real apache/doris#67916 documents: they verify after relabelling with the
closed vocabulary, a test-coverage regression is rejected without a rationale
and accepted with one, and a functional-bug regression rated Minor is
rejected; that review's own header already had BASE_SHA != MERGE_BASE
(TARGET_AHEAD = 5).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H2in7A8yA4qQ3LwAghueTR
@morningman

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for one P1 correctness issue: the name-normalization path can bypass the new JDBC-code fallback for legal alias identifiers and declare the wrong FE schema.

Checkpoint conclusions:

  • Goal/correctness and tests: ordinary underscore-named aliases resolve correctly, but the feature remains incorrect for legal aliases whose unqualified names are truncated to or collide with system names; current tests do not cover that case.
  • Minimal scope: the eight-file change is focused, and the declared binary/vendor-code exclusions were respected during review.
  • Concurrency and lifecycle: no new shared state, locking, background work, initialization, or cleanup behavior.
  • Configuration: no new variable; existing enable.mapping.varbinary behavior remains scoped to the native-name path.
  • Compatibility and parallel paths: no persisted/protocol compatibility change. Both plugin and legacy metadata paths were traced through their callers and SQL Server scanners; both contain the same name-preemption defect, while their other added mappings and runtime object shapes agree.
  • Conditionals: the new name-first/default-fallback branching is the identified failure point; the remaining supported/unsupported branches match the stated scope.
  • Test coverage and results: the unit and external fixtures are otherwise internally consistent, deterministic, and cover both clients plus positive/negative families. This was a static review only; no builds or tests were run independently under the runner contract. Exact-head CI currently reports compile, CheckStyle, FE UT, and External Regression passing.
  • Observability: no new service/runtime control path requiring metrics or logging; existing unsupported-type reporting is unchanged.
  • Persistence, transactions, data writes, and FE/BE variables: none in production code; SQL writes are test fixtures only.
  • Performance: only constant-size metadata dispatch is added; no material performance concern found.
  • Other issues and user focus: no additional user focus was supplied, and no other distinct issue remained after two convergence rounds and duplicate fencing.

Overall: one distinct blocking finding at the exact reviewed head.

// so that they never reach the JDBC type code fallback below.
return ConnectorType.of("UNSUPPORTED");
default:
return jdbcTypeCodeToConnectorType(fieldInfo);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Route legal alias identifiers through the base-code fallback

SQL Server permits alias type names to be delimited identifiers containing spaces or parentheses (CREATE TYPE, identifier rules). For CREATE TYPE dbo.[int alias] FROM varchar(50), getColumns() supplies TYPE_NAME = int alias and the base DATA_TYPE = VARCHAR; the normalization at line 58 reduces the name to int, so this fallback is never reached and FE exposes the VARCHAR column as INT. The legacy client has the same preemption. Please restrict IDENTITY normalization to a code-compatible IDENTITY form (or otherwise prefer unambiguous base codes before name dispatch) and cover legal alias names and system-name collisions in both paths.

…ame when its code agrees

An alias type may legally be named with spaces or parentheses:
CREATE TYPE dbo.[int alias] FROM varchar(50) is reported by getColumns()
with TYPE_NAME "int alias" and DATA_TYPE VARCHAR. Both SQL Server
clients cut the name at the first space or parenthesis to strip the
IDENTITY decoration ("int identity", "decimal(18,0) identity"), which
turned such an alias into the system type its name starts with and
declared the column as INT.

Strip the decoration only when the name has the IDENTITY form of one of
the base types IDENTITY is allowed on and DATA_TYPE is that base type's
code; any other name is matched as it is, so an alias name that is not a
system type name falls through to the JDBC type code as intended (an
alias cannot share a system type's name: SQL Server rejects it).

Unit tests cover such alias names and the IDENTITY forms the driver
versions report; the docker fixture gains dbo.test_alias_name with
[int alias], [decimal(18,0) identity] and [int identity] aliases next to
a real IDENTITY column.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@morningman

Copy link
Copy Markdown
Contributor Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 16694 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 80fe649113ebee7203507478875676caaa39fc86, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17625	3065	3022	3022
q2	2087	251	212	212
q3	10268	894	511	511
q4	4673	251	204	204
q5	7671	576	383	383
q6	138	113	97	97
q7	537	540	392	392
q8	9233	906	911	906
q9	3455	2389	2382	2382
q10	6505	854	715	715
q11	408	198	183	183
q12	616	257	201	201
q13	18166	1516	1160	1160
q14	157	149	141	141
q15	q16	447	393	370	370
q17	1421	899	794	794
q18	3063	2263	2232	2232
q19	1126	906	761	761
q20	373	286	203	203
q21	5312	1597	1863	1597
q22	340	272	228	228
Total cold run time: 93621 ms
Total hot run time: 16694 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	3432	3311	3324	3311
q2	496	401	389	389
q3	2203	2308	2198	2198
q4	1194	1173	894	894
q5	2145	2112	2101	2101
q6	172	125	89	89
q7	1017	922	857	857
q8	1598	1402	1396	1396
q9	3108	3082	3098	3082
q10	1831	1809	1664	1664
q11	355	270	249	249
q12	448	429	342	342
q13	1471	1538	1146	1146
q14	177	169	166	166
q15	q16	390	399	362	362
q17	3553	3356	3194	3194
q18	4834	4424	4687	4424
q19	869	801	890	801
q20	1025	1005	811	811
q21	3824	3118	3348	3118
q22	397	341	308	308
Total cold run time: 34539 ms
Total hot run time: 30902 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 82256 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 80fe649113ebee7203507478875676caaa39fc86, data reload: false

query5	4251	419	337	337
query6	372	139	132	132
query7	4944	428	230	230
query8	291	126	115	115
query9	8679	2909	2885	2885
query10	391	220	182	182
query11	5419	1043	918	918
query12	117	71	75	71
query13	1186	449	322	322
query14	5971	2250	2159	2159
query14_1	2040	2049	1999	1999
query15	178	115	111	111
query16	902	379	376	376
query17	786	459	359	359
query18	2330	325	233	233
query19	163	138	110	110
query20	75	68	73	68
query21	200	101	90	90
query22	5425	5383	5375	5375
query23	6719	6314	6008	6008
query23_1	6000	6047	6152	6047
query24	7298	1106	761	761
query24_1	791	769	786	769
query25	424	298	253	253
query26	1221	221	132	132
query27	2796	421	243	243
query28	4726	1508	1504	1504
query29	926	445	354	354
query30	242	152	130	130
query31	829	398	330	330
query32	129	77	72	72
query33	469	224	184	184
query34	993	850	483	483
query35	411	403	357	357
query36	576	572	531	531
query37	125	86	70	70
query38	1011	857	834	834
query39	511	483	478	478
query39_1	474	492	442	442
query40	205	92	82	82
query41	61	58	56	56
query42	75	71	73	71
query43	249	246	220	220
query44	986	538	537	537
query45	114	102	99	99
query46	775	838	525	525
query47	780	754	713	713
query48	331	309	224	224
query49	533	236	193	193
query50	752	258	188	188
query51	8146	8111	8095	8095
query52	73	65	58	58
query53	192	198	141	141
query54	196	164	149	149
query55	74	57	66	57
query56	317	168	167	167
query57	705	622	640	622
query58	187	174	161	161
query59	1236	1234	1098	1098
query60	258	187	173	173
query61	117	118	107	107
query62	356	197	177	177
query63	167	139	141	139
query64	2815	733	638	638
query65	1630	1611	1656	1611
query66	1940	265	201	201
query67	10183	9837	9847	9837
query68	2989	1174	750	750
query69	347	211	198	198
query70	675	593	577	577
query71	253	176	164	164
query72	2264	1687	1519	1519
query73	650	606	345	345
query74	2012	1224	1147	1147
query75	1193	1102	982	982
query76	2385	706	493	493
query77	265	248	210	210
query78	3884	3711	3241	3241
query79	2097	830	581	581
query80	1477	314	259	259
query81	488	153	130	130
query82	635	132	103	103
query83	278	210	187	187
query84	292	109	85	85
query85	768	343	281	281
query86	387	179	176	176
query87	1006	955	905	905
query88	2740	2107	2087	2087
query89	288	193	175	175
query90	2000	127	125	125
query91	129	116	102	102
query92	77	68	70	68
query93	1360	1043	702	702
query94	617	253	180	180
query95	517	244	311	244
query96	875	579	262	262
query97	1066	1067	978	978
query98	143	135	132	132
query99	421	358	311	311
Total cold run time: 177838 ms
Total hot run time: 82256 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 14.65 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 80fe649113ebee7203507478875676caaa39fc86, data reload: false

query1	0.01	0.01	0.00
query2	0.08	0.04	0.04
query3	0.25	0.11	0.11
query4	1.60	0.10	0.10
query5	0.17	0.16	0.15
query6	1.27	0.69	0.68
query7	0.04	0.01	0.00
query8	0.05	0.03	0.03
query9	0.28	0.21	0.22
query10	0.34	0.34	0.34
query11	0.16	0.12	0.12
query12	0.15	0.13	0.12
query13	0.29	0.31	0.30
query14	0.45	0.44	0.45
query15	0.36	0.36	0.34
query16	0.22	0.20	0.23
query17	0.70	0.71	0.69
query18	0.19	0.17	0.17
query19	1.27	1.19	1.18
query20	0.02	0.01	0.01
query21	15.48	0.16	0.11
query22	5.09	0.05	0.04
query23	16.19	0.26	0.10
query24	2.98	0.32	0.25
query25	0.11	0.04	0.04
query26	0.83	0.17	0.11
query27	0.04	0.03	0.03
query28	3.67	0.57	0.27
query29	12.47	3.21	2.55
query30	0.25	0.11	0.12
query31	2.76	0.37	0.17
query32	3.53	0.33	0.23
query33	1.49	1.40	1.44
query34	15.37	2.20	1.77
query35	1.74	1.73	1.74
query36	0.45	0.29	0.29
query37	0.06	0.04	0.03
query38	0.04	0.03	0.02
query39	0.04	0.02	0.02
query40	0.11	0.09	0.08
query41	0.07	0.02	0.02
query42	0.03	0.03	0.02
query43	0.03	0.03	0.03
Total cold run time: 90.73 s
Total hot run time: 14.65 s

@morningman

Copy link
Copy Markdown
Contributor Author

Local pipeline review — ✅ PASS

schema: doris-repo-review/v1
status: PASS
pr: apache/doris#67916
commit: 80fe649113ebee7203507478875676caaa39fc86
base: 2573820600eb178150a35710a94fd58b478df96d
reviewed_at: 2026-09-14T17:40+08:00
reviewer: morningman
model: claude-opus-5
effort: max
findings: {blocker: 0, major: 0, minor: 2, nit: 2}
rounds: 1
converged: true

Notes for maintainers

  • The CI review bot's P1 is fixed and verified in both clients and end to end (test_alias_name): delimited alias names are no longer cut to a system type name. Note for the record: the 39de212 review dismissed "alias names with spaces" as covered by the code fallback without checking the collision with a system-type prefix; the collision pre-existed at the base.
  • fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcSQLServerClient.java:55 — F-03 (Nit): the new identityBaseType gate is outcome-neutral — for every IDENTITY-eligible base the code fallback returns the same Doris type as the name path, so dropping the truncation alone fixes the P1 identically; numeric(18, 0) identity / decimal(18,0) IDENTITY(1,1) are not forms any driver produces (TYPE_NAME is the server's spt_datatype_info string verbatim: int identity, decimal() identity, numeric() identity).
  • fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcSQLServerConnectorClient.java:97 — F-02 (Minor, pre-existing): the connector lowercases TYPE_NAME while fe-core does not; the PR body's "SQL Server rejects CREATE TYPE dbo.[int]" was observed on a case-insensitive collation only — on a CS collation dbo.[INT] FROM varchar(10) would map to INT here. System type names are lowercase on both metadata paths, so dropping the lowercasing is the safe direction.
  • fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcSQLServerClient.java:211 — F-01 (Minor, by design): aliases over datetimeoffset/binary/image (unambiguous codes) stay UNSUPPORTED, now pinned by the negative fixture; with the P1 fix an alias named like a binary type over that base ([varbinary alias] FROM varbinary) loses the readability it had by truncation accident — worth listing in the "Deliberately not resolved" paragraph or resolving via SS_UDT_ASSEMBLY_TYPE_NAME / SQL_DATA_TYPE.
  • The suite is tagged p2,external and the External Regression pipeline sets excludeGroups = "p1,p2", so CI never executes it; the author's local run against SQL Server 2022 is the only execution — the PR body should say so ("nine blocks, run locally at 80fe649"), and the release note should exclude the five UNSUPPORTED families.

Reviewed locally with the doris-repo-review pipeline. Repository policy may accept this receipt for the matching commit; it is not a human Apache approval.

@morningman
morningman merged commit ee17a0a into apache:master Sep 14, 2026
50 of 51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] [JDBC Catalog] SQL Server user-defined alias data types map to UNSUPPORTED_TYPE

3 participants