@@ -759,6 +759,49 @@ def is_numeric_type_code(type_code, dialect_name: str) -> bool:
759759 return False
760760
761761
762+ def is_mssql_string_type_code (type_code ) -> bool :
763+ """
764+ 判断 SQL Server (pymssql) 游标描述中的 type_code 是否为字符串类型。
765+
766+ pymssql 的 varchar/char/nvarchar/nchar/text 等字符串类型的 type_code 为
767+ STRING(1),而数值/日期等类型分别为 NUMBER(3)、DATETIME(4) 等。
768+
769+ Args:
770+ type_code: cursor.description[col][1] 的值
771+
772+ Returns:
773+ bool: 是否为字符串(varchar 等)类型
774+ """
775+ try :
776+ return type_code == 1
777+ except Exception :
778+ return False
779+
780+
781+ def convert_gbk_string (value ):
782+ """
783+ 将 SQL Server 中以 latin-1 读取出的乱码字符串转换为 GBK 编码的正确文本。
784+
785+ 当 varchar 列实际存储的是 GBK 字节(被错误地按 latin-1 解码)时,
786+ 通过 str.encode('latin-1').decode('gbk') 还原。转换中任一步失败则返回原值。
787+ """
788+ if not isinstance (value , str ):
789+ return value
790+ try :
791+ return value .encode ('latin-1' ).decode ('gbk' )
792+ except (UnicodeEncodeError , UnicodeDecodeError ):
793+ return value
794+
795+
796+ def convert_mssql_value (value , col_idx , string_col_idx_set , is_mssql ):
797+ """
798+ 对 SQL Server 结果集中字符串列的值进行 GBK 编码转换。
799+ """
800+ if is_mssql and col_idx in string_col_idx_set :
801+ return convert_gbk_string (value )
802+ return value
803+
804+
762805def exec_sql (ds : CoreDatasource | AssistantOutDsSchema , sql : str , origin_column = False ):
763806 while sql .endswith (';' ):
764807 sql = sql [:- 1 ]
@@ -777,13 +820,19 @@ def exec_sql(ds: CoreDatasource | AssistantOutDsSchema, sql: str, origin_column=
777820 try :
778821 columns = result .keys ()._keys if origin_column else [item .lower () for item in result .keys ()._keys ]
779822
823+ # SQL Server varchar 等字符串列需做 GBK 编码转换
824+ is_mssql = dialect_name == 'mssql'
825+ string_cols = []
826+
780827 fields_info = []
781828
782829 for col_idx , col_name in enumerate (columns ):
783830 is_numeric = False
784831 try :
785832 type_code = result .cursor .description [col_idx ][1 ]
786833 is_numeric = is_numeric_type_code (type_code , dialect_name )
834+ if is_mssql and is_mssql_string_type_code (type_code ):
835+ string_cols .append (col_idx )
787836 except (IndexError , AttributeError ):
788837 pass
789838
@@ -792,9 +841,12 @@ def exec_sql(ds: CoreDatasource | AssistantOutDsSchema, sql: str, origin_column=
792841 "is_numeric" : is_numeric
793842 })
794843
844+ string_col_idx_set = set (string_cols )
845+
795846 res = result .fetchall ()
796847 result_list = [
797- {str (columns [i ]): convert_value (value ) for i , value in enumerate (tuple_item )} for tuple_item in
848+ {str (columns [i ]): convert_mssql_value (convert_value (value ), i , string_col_idx_set , is_mssql )
849+ for i , value in enumerate (tuple_item )} for tuple_item in
798850 res
799851 ]
800852 return {"fields" : columns , "data" : result_list , "fields_info" : fields_info ,
0 commit comments