9797#define ESINFO_KEY_VERSION "version"
9898#define ESINFO_KEY_NUMBER "number"
9999
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+
100105/* structure for one row returned by the ES.
101106 * This is a mirror of elasticsearch_type, with length-or-indicator fields
102107 * for each of the members in elasticsearch_type */
@@ -1411,28 +1416,6 @@ SQLRETURN config_dbc(esodbc_dbc_st *dbc, esodbc_dsn_attrs_st *attrs)
14111416 goto err ;
14121417 }
14131418
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-
14361419 /* "multifield leniency" param */
14371420 dbc -> mfield_lenient = wstr2bool (& attrs -> mfield_lenient );
14381421 INFOH (dbc , "multifield lenient: %s." ,
@@ -1523,10 +1506,10 @@ void cleanup_dbc(esodbc_dbc_st *dbc)
15231506 } else {
15241507 assert (dbc -> no_types == 0 );
15251508 }
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 ;
15301513 }
15311514 if (dbc -> catalog .str ) {
15321515 free (dbc -> catalog .str );
@@ -1652,10 +1635,59 @@ static BOOL parse_es_version_json(esodbc_dbc_st *dbc, cstr_st *rsp_body,
16521635 return FALSE;
16531636 }
16541637 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 "`." ,
16561639 version -> cnt , LWSTR (version ));
16571640 return TRUE;
16581641}
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+
16591691/*
16601692 * Note: not thread safe: only usable on connection setup.
16611693 */
@@ -1667,16 +1699,17 @@ static SQLRETURN check_server_version(esodbc_dbc_st *dbc)
16671699 BOOL is_json ;
16681700 SQLRETURN ret ;
16691701 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 ;
16731704 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." ;
16771710 /* 32: max length of the version strings for which the explicit message
16781711 * 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 ];
16801713 int n ;
16811714
16821715 ret = dbc_curl_set_url (dbc , ESODBC_CURL_ROOT );
@@ -1711,54 +1744,43 @@ static SQLRETURN check_server_version(esodbc_dbc_st *dbc)
17111744 goto err ;
17121745 }
17131746
1714- ver_checking = dbc -> srv_ver .checking ;
17151747 /* 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 ) {
17181750 ERRNH (dbc , "OOM for %zu." , (n + 1 ) * sizeof (SQLWCHAR ));
17191751 post_diagnostic (dbc , SQL_STATE_HY001 , NULL , 0 );
17201752 goto err ;
17211753 } 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 ) {
17241756 /* non-ASCII or empty */
1725- ERRH (dbc , "Elasticsearch version string is invalid." );
1757+ BUGH (dbc , "Elasticsearch version string is invalid." );
17261758 goto err ;
17271759 }
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 ;
17311762
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 );
17591779 } 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 ;
17621784 }
17631785
17641786 free (rsp_body .str );
0 commit comments