97
97
#define ESINFO_KEY_VERSION "version"
98
98
#define ESINFO_KEY_NUMBER "number"
99
99
100
+ /* "base" of the version number (how many values supported for each version
101
+ * constituent: major, minor, revision) */
102
+ #define VER_LEVEL_MULTI 100L
103
+
104
+
100
105
/* structure for one row returned by the ES.
101
106
* This is a mirror of elasticsearch_type, with length-or-indicator fields
102
107
* for each of the members in elasticsearch_type */
@@ -1411,28 +1416,6 @@ SQLRETURN config_dbc(esodbc_dbc_st *dbc, esodbc_dsn_attrs_st *attrs)
1411
1416
goto err ;
1412
1417
}
1413
1418
1414
- /*
1415
- * Version checking mode
1416
- */
1417
- if (EQ_CASE_WSTR (& attrs -> version_checking ,
1418
- & MK_WSTR (ESODBC_DSN_VC_STRICT ))
1419
- || EQ_CASE_WSTR (& attrs -> version_checking ,
1420
- & MK_WSTR (ESODBC_DSN_VC_MAJOR ))
1421
- # ifndef NDEBUG
1422
- || EQ_CASE_WSTR (& attrs -> version_checking ,
1423
- & MK_WSTR (ESODBC_DSN_VC_NONE ))
1424
- # endif /* NDEBUG */
1425
- ) {
1426
- dbc -> srv_ver .checking = (unsigned char )attrs -> version_checking .str [0 ];
1427
- DBGH (dbc , "version checking mode: %c." , dbc -> srv_ver .checking );
1428
- } else {
1429
- ERRH (dbc , "unknown version checking mode '" LWPDL "'." ,
1430
- LWSTR (& attrs -> version_checking ));
1431
- SET_HDIAG (dbc , SQL_STATE_HY000 , "invalid version checking mode "
1432
- "setting" , 0 );
1433
- goto err ;
1434
- }
1435
-
1436
1419
/* "multifield leniency" param */
1437
1420
dbc -> mfield_lenient = wstr2bool (& attrs -> mfield_lenient );
1438
1421
INFOH (dbc , "multifield lenient: %s." ,
@@ -1523,10 +1506,10 @@ void cleanup_dbc(esodbc_dbc_st *dbc)
1523
1506
} else {
1524
1507
assert (dbc -> no_types == 0 );
1525
1508
}
1526
- if (dbc -> srv_ver .string . cnt ) { /* .str might be compromized by the union */
1527
- free (dbc -> srv_ver .string . str );
1528
- dbc -> srv_ver .string . str = NULL ;
1529
- dbc -> srv_ver .string . cnt = 0 ;
1509
+ if (dbc -> srv_ver .str ) {
1510
+ free (dbc -> srv_ver .str );
1511
+ dbc -> srv_ver .str = NULL ;
1512
+ dbc -> srv_ver .cnt = 0 ;
1530
1513
}
1531
1514
if (dbc -> catalog .str ) {
1532
1515
free (dbc -> catalog .str );
@@ -1652,10 +1635,59 @@ static BOOL parse_es_version_json(esodbc_dbc_st *dbc, cstr_st *rsp_body,
1652
1635
return FALSE;
1653
1636
}
1654
1637
version -> str = (SQLWCHAR * )UJReadString (o_number , & version -> cnt );
1655
- DBGH (dbc , "Elasticsearch'es version number: [%zu] `" LWPDL "`." ,
1638
+ DBGH (dbc , "Elasticsearch's version number: [%zu] `" LWPDL "`." ,
1656
1639
version -> cnt , LWSTR (version ));
1657
1640
return TRUE;
1658
1641
}
1642
+
1643
+ /* parses a Major.Minor.Revison version format and returns a numerical value
1644
+ * of it */
1645
+ static long version_to_id (wstr_st * ver )
1646
+ {
1647
+ SQLWCHAR * stop ;
1648
+ long id , val ;
1649
+
1650
+ assert (ver -> str [ver -> cnt ] == L'\0' );
1651
+
1652
+ errno = 0 ;
1653
+ stop = ver -> str ;
1654
+
1655
+ /* parse major */
1656
+ id = wcstol (stop , & stop , /*base*/ 10 );
1657
+ if (errno || VER_LEVEL_MULTI <= id || id <= 0 ) {
1658
+ return -1 ;
1659
+ }
1660
+ if (* stop != L'.' ) {
1661
+ return -1 ;
1662
+ } else {
1663
+ stop ++ ;
1664
+ }
1665
+ id *= VER_LEVEL_MULTI ;
1666
+
1667
+ /* parse minor */
1668
+ val = wcstol (stop , & stop , /*base*/ 10 );
1669
+ if (errno || VER_LEVEL_MULTI <= val || val < 0 ) {
1670
+ return -1 ;
1671
+ }
1672
+ if (* stop != L'.' ) {
1673
+ return -1 ;
1674
+ } else {
1675
+ stop ++ ;
1676
+ }
1677
+ id += val ;
1678
+ id *= VER_LEVEL_MULTI ;
1679
+
1680
+ /* parse minor */
1681
+ val = wcstol (stop , & stop , /*base*/ 10 );
1682
+ if (errno || VER_LEVEL_MULTI <= val || val < 0 ) {
1683
+ return -1 ;
1684
+ }
1685
+ id += val ;
1686
+ id *= VER_LEVEL_MULTI ;
1687
+
1688
+ return id ;
1689
+ }
1690
+
1659
1691
/*
1660
1692
* Note: not thread safe: only usable on connection setup.
1661
1693
*/
@@ -1667,16 +1699,17 @@ static SQLRETURN check_server_version(esodbc_dbc_st *dbc)
1667
1699
BOOL is_json ;
1668
1700
SQLRETURN ret ;
1669
1701
void * state = NULL ;
1670
- unsigned char ver_checking ;
1671
- wstr_st own_ver = WSTR_INIT (STR (DRV_VERSION )); /*build-time define*/
1672
- wstr_st es_ver , ver_no ;
1702
+ static wstr_st min_es_ver = WSTR_INIT (ESODBC_MIN_ES_VER );
1703
+ wstr_st es_ver ;
1673
1704
cstr_st es_ver_c ;
1674
- static const wchar_t err_msg_fmt [] = L"Version mismatch between server ("
1675
- WPFWP_LDESC ") and driver (" WPFWP_LDESC "). Please use a driver whose"
1676
- " version matches that of your server." ;
1705
+ long es_ver_l , min_es_ver_l ;
1706
+ static const wchar_t err_msg_fmt [] = L"Elasticsearch's version ("
1707
+ WPFWP_LDESC ") is below minimum required (" ESODBC_MIN_ES_VER ") "
1708
+ "version. Please use a driver whose version matches that of your "
1709
+ "server." ;
1677
1710
/* 32: max length of the version strings for which the explicit message
1678
1711
* above is provided. */
1679
- SQLWCHAR wbuff [sizeof (err_msg_fmt )/sizeof (err_msg_fmt [0 ]) + 2 * 32 ];
1712
+ SQLWCHAR wbuff [sizeof (err_msg_fmt )/sizeof (err_msg_fmt [0 ]) + 32 ];
1680
1713
int n ;
1681
1714
1682
1715
ret = dbc_curl_set_url (dbc , ESODBC_CURL_ROOT );
@@ -1711,54 +1744,43 @@ static SQLRETURN check_server_version(esodbc_dbc_st *dbc)
1711
1744
goto err ;
1712
1745
}
1713
1746
1714
- ver_checking = dbc -> srv_ver .checking ;
1715
1747
/* version is returned to application, which requires a NTS => +1 for \0 */
1716
- dbc -> srv_ver .string . str = malloc ((n + 1 ) * sizeof (SQLWCHAR ));
1717
- if (! dbc -> srv_ver .string . str ) {
1748
+ dbc -> srv_ver .str = malloc ((n + 1 ) * sizeof (SQLWCHAR ));
1749
+ if (! dbc -> srv_ver .str ) {
1718
1750
ERRNH (dbc , "OOM for %zu." , (n + 1 ) * sizeof (SQLWCHAR ));
1719
1751
post_diagnostic (dbc , SQL_STATE_HY001 , NULL , 0 );
1720
1752
goto err ;
1721
1753
} else if (is_json ) {
1722
- memcpy (dbc -> srv_ver .string . str , es_ver .str , n * sizeof (SQLWCHAR ));
1723
- } else if (ascii_c2w (es_ver_c .str , dbc -> srv_ver .string . str , n ) < 0 ) {
1754
+ memcpy (dbc -> srv_ver .str , es_ver .str , n * sizeof (SQLWCHAR ));
1755
+ } else if (ascii_c2w (es_ver_c .str , dbc -> srv_ver .str , n ) < 0 ) {
1724
1756
/* non-ASCII or empty */
1725
- ERRH (dbc , "Elasticsearch version string is invalid." );
1757
+ BUGH (dbc , "Elasticsearch version string is invalid." );
1726
1758
goto err ;
1727
1759
}
1728
- dbc -> srv_ver .string .cnt = n ;
1729
- dbc -> srv_ver .string .str [n ] = 0 ;
1730
- ver_no = dbc -> srv_ver .string ;
1760
+ dbc -> srv_ver .cnt = n ;
1761
+ dbc -> srv_ver .str [n ] = 0 ;
1731
1762
1732
- # ifndef NDEBUG
1733
- /* strip any qualifiers (=anything following a first `-`) in debug mode */
1734
- wtrim_at (& ver_no , L'-' );
1735
- wtrim_at (& own_ver , L'-' );
1736
- # endif /* !NDEBUG */
1737
-
1738
- if (tolower (ver_checking ) == tolower (ESODBC_DSN_VC_MAJOR [0 ])) {
1739
- /* trim versions to the first dot, i.e. major version */
1740
- wtrim_at (& ver_no , L'.' );
1741
- wtrim_at (& own_ver , L'.' );
1742
- }
1743
-
1744
- if (tolower (ver_checking ) != tolower (ESODBC_DSN_VC_NONE [0 ])) {
1745
- if (! EQ_WSTR (& ver_no , & own_ver )) {
1746
- ERRH (dbc , "version mismatch: server: " LWPDL ", "
1747
- "own: " LWPDL "." , LWSTR (& ver_no ), LWSTR (& own_ver ));
1748
- n = swprintf (wbuff , sizeof (wbuff )/sizeof (wbuff [0 ]),
1749
- err_msg_fmt , LWSTR (& ver_no ), LWSTR (& own_ver ));
1750
- ret = post_diagnostic (dbc , SQL_STATE_HY000 , (n <= 0 ) ?
1751
- L"Version mismatch between server and driver" :
1752
- wbuff , 0 );
1753
- } else {
1754
- INFOH (dbc , "server and driver versions aligned to: " LWPDL "." ,
1755
- LWSTR (& own_ver ));
1756
- ret = SQL_SUCCESS ;
1757
- }
1758
- # ifndef NDEBUG
1763
+ min_es_ver_l = version_to_id (& min_es_ver );
1764
+ assert (0 < min_es_ver_l );
1765
+ es_ver_l = version_to_id (& dbc -> srv_ver );
1766
+ if (es_ver_l <= 0 ) {
1767
+ BUGH (dbc , "failed to parse Elasticsearch version `" LWPDL "`." ,
1768
+ LWSTR (& dbc -> srv_ver ));
1769
+ goto err ;
1770
+ }
1771
+ if (es_ver_l < min_es_ver_l ) {
1772
+ ERRH (dbc , "Elasticsearch version `" LWPDL "` is below minimum required"
1773
+ " `" LWPDL "`." , LWSTR (& dbc -> srv_ver ), LWSTR (& min_es_ver ));
1774
+ n = swprintf (wbuff , sizeof (wbuff )/sizeof (wbuff [0 ]),
1775
+ err_msg_fmt , LWSTR (& dbc -> srv_ver ));
1776
+ ret = post_diagnostic (dbc , SQL_STATE_HY000 , (n <= 0 ) ?
1777
+ L"Version mismatch between server and driver" :
1778
+ wbuff , 0 );
1759
1779
} else {
1760
- WARNH (dbc , "version checking disabled." );
1761
- # endif /* !NDEBUG */
1780
+ INFOH (dbc , "server version (" LWPDL ") %s minimum required "
1781
+ "(" ESODBC_MIN_ES_VER ")." , LWSTR (& dbc -> srv_ver ),
1782
+ es_ver_l == min_es_ver_l ? "meets" : "exceeds" );
1783
+ ret = SQL_SUCCESS ;
1762
1784
}
1763
1785
1764
1786
free (rsp_body .str );
0 commit comments