@@ -113,6 +113,49 @@ typedef struct {
113
113
wstr_st trace_level ;
114
114
} config_attrs_st ;
115
115
116
+ /* structure for one row returned by the ES.
117
+ * This is a mirror of elasticsearch_type, with length-or-indicator fields
118
+ * for each of the members in elasticsearch_type */
119
+ typedef struct {
120
+ SQLWCHAR type_name [ESODBC_MAX_IDENTIFIER_LEN ];
121
+ SQLLEN type_name_loi ; /* _ length or indicator */
122
+ SQLSMALLINT data_type ;
123
+ SQLLEN data_type_loi ;
124
+ SQLINTEGER column_size ;
125
+ SQLLEN column_size_loi ;
126
+ SQLWCHAR literal_prefix [ESODBC_MAX_IDENTIFIER_LEN ];
127
+ SQLLEN literal_prefix_loi ;
128
+ SQLWCHAR literal_suffix [ESODBC_MAX_IDENTIFIER_LEN ];
129
+ SQLLEN literal_suffix_loi ;
130
+ SQLWCHAR create_params [ESODBC_MAX_IDENTIFIER_LEN ];
131
+ SQLLEN create_params_loi ;
132
+ SQLSMALLINT nullable ;
133
+ SQLLEN nullable_loi ;
134
+ SQLSMALLINT case_sensitive ;
135
+ SQLLEN case_sensitive_loi ;
136
+ SQLSMALLINT searchable ;
137
+ SQLLEN searchable_loi ;
138
+ SQLSMALLINT unsigned_attribute ;
139
+ SQLLEN unsigned_attribute_loi ;
140
+ SQLSMALLINT fixed_prec_scale ;
141
+ SQLLEN fixed_prec_scale_loi ;
142
+ SQLSMALLINT auto_unique_value ;
143
+ SQLLEN auto_unique_value_loi ;
144
+ SQLWCHAR local_type_name [ESODBC_MAX_IDENTIFIER_LEN ];
145
+ SQLLEN local_type_name_loi ;
146
+ SQLSMALLINT minimum_scale ;
147
+ SQLLEN minimum_scale_loi ;
148
+ SQLSMALLINT maximum_scale ;
149
+ SQLLEN maximum_scale_loi ;
150
+ SQLSMALLINT sql_data_type ;
151
+ SQLLEN sql_data_type_loi ;
152
+ SQLSMALLINT sql_datetime_sub ;
153
+ SQLLEN sql_datetime_sub_loi ;
154
+ SQLINTEGER num_prec_radix ;
155
+ SQLLEN num_prec_radix_loi ;
156
+ SQLSMALLINT interval_precision ;
157
+ SQLLEN interval_precision_loi ;
158
+ } estype_row_st ;
116
159
/*
117
160
* HTTP headers used for all requests (Content-Type, Accept).
118
161
*/
@@ -1366,6 +1409,141 @@ static void set_display_size(esodbc_estype_st *es_type)
1366
1409
}
1367
1410
}
1368
1411
1412
+ static BOOL bind_types_cols (esodbc_stmt_st * stmt , estype_row_st * type_row )
1413
+ {
1414
+
1415
+ /* bind one column */
1416
+ #define ES_TYPES_BINDCOL (_col_nr , _member , _c_type ) \
1417
+ do { \
1418
+ SQLPOINTER _ptr = _c_type == SQL_C_WCHAR ? \
1419
+ (SQLPOINTER)(uintptr_t)type_row[0]._member : \
1420
+ (SQLPOINTER)&type_row[0]._member; \
1421
+ if (! SQL_SUCCEEDED(EsSQLBindCol(stmt, _col_nr, _c_type, \
1422
+ _ptr, sizeof(type_row[0]._member), \
1423
+ &type_row[0]._member ## _loi))) { \
1424
+ ERRH(stmt, "failed to bind column #" STR(_col_nr) "."); \
1425
+ return FALSE; \
1426
+ } \
1427
+ } while (0)
1428
+
1429
+ ES_TYPES_BINDCOL (1 , type_name , SQL_C_WCHAR );
1430
+ ES_TYPES_BINDCOL (2 , data_type , SQL_C_SSHORT );
1431
+ ES_TYPES_BINDCOL (3 , column_size , SQL_C_SLONG );
1432
+ ES_TYPES_BINDCOL (4 , literal_prefix , SQL_C_WCHAR );
1433
+ ES_TYPES_BINDCOL (5 , literal_suffix , SQL_C_WCHAR );
1434
+ ES_TYPES_BINDCOL (6 , create_params , SQL_C_WCHAR );
1435
+ ES_TYPES_BINDCOL (7 , nullable , SQL_C_SSHORT );
1436
+ ES_TYPES_BINDCOL (8 , case_sensitive , SQL_C_SSHORT );
1437
+ ES_TYPES_BINDCOL (9 , searchable , SQL_C_SSHORT );
1438
+ ES_TYPES_BINDCOL (10 , unsigned_attribute , SQL_C_SSHORT );
1439
+ ES_TYPES_BINDCOL (11 , fixed_prec_scale , SQL_C_SSHORT );
1440
+ ES_TYPES_BINDCOL (12 , auto_unique_value , SQL_C_SSHORT );
1441
+ ES_TYPES_BINDCOL (13 , local_type_name , SQL_C_WCHAR );
1442
+ ES_TYPES_BINDCOL (14 , minimum_scale , SQL_C_SSHORT );
1443
+ ES_TYPES_BINDCOL (15 , maximum_scale , SQL_C_SSHORT );
1444
+ ES_TYPES_BINDCOL (16 , sql_data_type , SQL_C_SSHORT );
1445
+ ES_TYPES_BINDCOL (17 , sql_datetime_sub , SQL_C_SSHORT );
1446
+ ES_TYPES_BINDCOL (18 , num_prec_radix , SQL_C_SLONG );
1447
+ ES_TYPES_BINDCOL (19 , interval_precision , SQL_C_SSHORT );
1448
+
1449
+ #undef ES_TYPES_BINDCOL
1450
+
1451
+ return TRUE;
1452
+ }
1453
+
1454
+ static void * copy_types_rows (estype_row_st * type_row , SQLULEN rows_fetched ,
1455
+ esodbc_estype_st * types )
1456
+ {
1457
+ SQLWCHAR * pos ;
1458
+ int i ;
1459
+
1460
+ /* start pointer where the strings will be copied in */
1461
+ pos = (SQLWCHAR * )& types [rows_fetched ];
1462
+
1463
+ /* copy one integer member */
1464
+ #define ES_TYPES_COPY_INT (_member ) \
1465
+ do { \
1466
+ if (type_row[i]._member ## _loi == SQL_NULL_DATA) { \
1467
+ /*null->0 is harmless for cached types */ \
1468
+ types [i]._member = 0; \
1469
+ } else { \
1470
+ types[i]._member = type_row[i]._member; \
1471
+ } \
1472
+ } while (0)
1473
+ /* copy one wstr_st member
1474
+ * Note: it'll shift NULLs to empty strings, as most of the API asks for
1475
+ * empty strings if data is unavailable ("unkown"). */
1476
+ #define ES_TYPES_COPY_WSTR (_wmember ) \
1477
+ do { \
1478
+ if (type_row[i]._wmember ## _loi == SQL_NULL_DATA) { \
1479
+ types[i]._wmember.cnt = 0; \
1480
+ types[i]._wmember.str = MK_WPTR(""); \
1481
+ } else { \
1482
+ types[i]._wmember.cnt = \
1483
+ type_row[i]._wmember ## _loi / sizeof(SQLWCHAR); \
1484
+ types[i]._wmember.str = pos; \
1485
+ wmemcpy(types[i]._wmember.str, \
1486
+ type_row[i]._wmember, types[i]._wmember.cnt + /*\0*/ 1 ); \
1487
+ pos += types [i ]._wmember .cnt + /*\0*/ 1 ; \
1488
+ } \
1489
+ } while (0 )
1490
+
1491
+ for (i = 0 ; i < rows_fetched ; i ++ ) {
1492
+ /* copy data */
1493
+ ES_TYPES_COPY_WSTR (type_name );
1494
+ ES_TYPES_COPY_INT (data_type );
1495
+ ES_TYPES_COPY_INT (column_size );
1496
+ ES_TYPES_COPY_WSTR (literal_prefix );
1497
+ ES_TYPES_COPY_WSTR (literal_suffix );
1498
+ ES_TYPES_COPY_WSTR (create_params );
1499
+ ES_TYPES_COPY_INT (nullable );
1500
+ ES_TYPES_COPY_INT (case_sensitive );
1501
+ ES_TYPES_COPY_INT (searchable );
1502
+ ES_TYPES_COPY_INT (unsigned_attribute );
1503
+ ES_TYPES_COPY_INT (fixed_prec_scale );
1504
+ ES_TYPES_COPY_INT (auto_unique_value );
1505
+ ES_TYPES_COPY_WSTR (local_type_name );
1506
+ ES_TYPES_COPY_INT (minimum_scale );
1507
+ ES_TYPES_COPY_INT (maximum_scale );
1508
+ ES_TYPES_COPY_INT (sql_data_type );
1509
+ ES_TYPES_COPY_INT (sql_datetime_sub );
1510
+ ES_TYPES_COPY_INT (num_prec_radix );
1511
+ ES_TYPES_COPY_INT (interval_precision );
1512
+
1513
+ /* apply any needed fixes */
1514
+
1515
+ /* warn if scales extremes are different */
1516
+ if (types [i ].maximum_scale != types [i ].minimum_scale ) {
1517
+ ERR ("type `" LWPDL "` returned with non-equal max/min "
1518
+ "scale: %d/%d." , LWSTR (& types [i ].type_name ),
1519
+ types [i ].maximum_scale , types [i ].minimum_scale );
1520
+ }
1521
+
1522
+ /* resolve ES type to SQL C type */
1523
+ types [i ].c_concise_type = type_elastic2csql (& types [i ].type_name );
1524
+ if (types [i ].c_concise_type == SQL_UNKNOWN_TYPE ) {
1525
+ /* ES version newer than driver's? */
1526
+ ERR ("failed to convert type name `" LWPDL "` to SQL C type." ,
1527
+ LWSTR (& types [i ].type_name ));
1528
+ return NULL ;
1529
+ }
1530
+ /* set meta type */
1531
+ types [i ].meta_type = concise_to_meta (types [i ].c_concise_type ,
1532
+ /*C type -> AxD*/ DESC_TYPE_ARD );
1533
+
1534
+ /* fix SQL_DATA_TYPE and SQL_DATETIME_SUB columns TODO: GH issue */
1535
+ concise_to_type_code (types [i ].data_type , & types [i ].sql_data_type ,
1536
+ & types [i ].sql_datetime_sub );
1537
+
1538
+ set_display_size (types + i );
1539
+ }
1540
+
1541
+ #undef ES_TYPES_COPY_INT
1542
+ #undef ES_TYPES_COPY_WCHAR
1543
+
1544
+ return pos ;
1545
+ }
1546
+
1369
1547
/*
1370
1548
* Load SYS TYPES data.
1371
1549
*
@@ -1380,56 +1558,14 @@ static BOOL load_es_types(esodbc_dbc_st *dbc)
1380
1558
SQLRETURN ret = FALSE;
1381
1559
SQLSMALLINT col_cnt ;
1382
1560
SQLLEN row_cnt ;
1383
- /* structure for one row returned by the ES.
1384
- * This is a mirror of elasticsearch_type, with length-or-indicator fields
1385
- * for each of the members in elasticsearch_type */
1386
- struct {
1387
- SQLWCHAR type_name [ESODBC_MAX_IDENTIFIER_LEN ];
1388
- SQLLEN type_name_loi ; /* _ length or indicator */
1389
- SQLSMALLINT data_type ;
1390
- SQLLEN data_type_loi ;
1391
- SQLINTEGER column_size ;
1392
- SQLLEN column_size_loi ;
1393
- SQLWCHAR literal_prefix [ESODBC_MAX_IDENTIFIER_LEN ];
1394
- SQLLEN literal_prefix_loi ;
1395
- SQLWCHAR literal_suffix [ESODBC_MAX_IDENTIFIER_LEN ];
1396
- SQLLEN literal_suffix_loi ;
1397
- SQLWCHAR create_params [ESODBC_MAX_IDENTIFIER_LEN ];
1398
- SQLLEN create_params_loi ;
1399
- SQLSMALLINT nullable ;
1400
- SQLLEN nullable_loi ;
1401
- SQLSMALLINT case_sensitive ;
1402
- SQLLEN case_sensitive_loi ;
1403
- SQLSMALLINT searchable ;
1404
- SQLLEN searchable_loi ;
1405
- SQLSMALLINT unsigned_attribute ;
1406
- SQLLEN unsigned_attribute_loi ;
1407
- SQLSMALLINT fixed_prec_scale ;
1408
- SQLLEN fixed_prec_scale_loi ;
1409
- SQLSMALLINT auto_unique_value ;
1410
- SQLLEN auto_unique_value_loi ;
1411
- SQLWCHAR local_type_name [ESODBC_MAX_IDENTIFIER_LEN ];
1412
- SQLLEN local_type_name_loi ;
1413
- SQLSMALLINT minimum_scale ;
1414
- SQLLEN minimum_scale_loi ;
1415
- SQLSMALLINT maximum_scale ;
1416
- SQLLEN maximum_scale_loi ;
1417
- SQLSMALLINT sql_data_type ;
1418
- SQLLEN sql_data_type_loi ;
1419
- SQLSMALLINT sql_datetime_sub ;
1420
- SQLLEN sql_datetime_sub_loi ;
1421
- SQLINTEGER num_prec_radix ;
1422
- SQLLEN num_prec_radix_loi ;
1423
- SQLSMALLINT interval_precision ;
1424
- SQLLEN interval_precision_loi ;
1425
- } type_row [ESODBC_MAX_ROW_ARRAY_SIZE ];
1426
- /* both arrays must use ESODBC_MAX_ROW_ARRAY_SIZE since no SQLFetch()
1561
+ /* both arrays below must use ESODBC_MAX_ROW_ARRAY_SIZE since no SQLFetch()
1427
1562
* looping is implemented (see check after SQLFetch() below). */
1563
+ estype_row_st type_row [ESODBC_MAX_ROW_ARRAY_SIZE ];
1428
1564
SQLUSMALLINT row_status [ESODBC_MAX_ROW_ARRAY_SIZE ];
1429
1565
SQLULEN rows_fetched , i , strs_len ;
1430
1566
size_t size ;
1431
- SQLWCHAR * pos ;
1432
1567
esodbc_estype_st * types = NULL ;
1568
+ void * pos ;
1433
1569
1434
1570
if (! SQL_SUCCEEDED (EsSQLAllocHandle (SQL_HANDLE_STMT , dbc , & stmt ))) {
1435
1571
ERRH (dbc , "failed to alloc a statement handle." );
@@ -1499,41 +1635,9 @@ static BOOL load_es_types(esodbc_dbc_st *dbc)
1499
1635
goto end ;
1500
1636
}
1501
1637
1502
- /* bind one column */
1503
- #define ES_TYPES_BINDCOL (_col_nr , _member , _c_type ) \
1504
- do { \
1505
- SQLPOINTER _ptr = _c_type == SQL_C_WCHAR ? \
1506
- (SQLPOINTER)(uintptr_t)type_row[0]._member : \
1507
- (SQLPOINTER)&type_row[0]._member; \
1508
- if (! SQL_SUCCEEDED(EsSQLBindCol(stmt, _col_nr, _c_type, \
1509
- _ptr, sizeof(type_row[0]._member), \
1510
- &type_row[0]._member ## _loi))) { \
1511
- ERRH(stmt, "failed to bind column #" STR(_col_nr) "."); \
1512
- goto end; \
1513
- } \
1514
- } while (0)
1515
-
1516
- ES_TYPES_BINDCOL (1 , type_name , SQL_C_WCHAR );
1517
- ES_TYPES_BINDCOL (2 , data_type , SQL_C_SSHORT );
1518
- ES_TYPES_BINDCOL (3 , column_size , SQL_C_SLONG );
1519
- ES_TYPES_BINDCOL (4 , literal_prefix , SQL_C_WCHAR );
1520
- ES_TYPES_BINDCOL (5 , literal_suffix , SQL_C_WCHAR );
1521
- ES_TYPES_BINDCOL (6 , create_params , SQL_C_WCHAR );
1522
- ES_TYPES_BINDCOL (7 , nullable , SQL_C_SSHORT );
1523
- ES_TYPES_BINDCOL (8 , case_sensitive , SQL_C_SSHORT );
1524
- ES_TYPES_BINDCOL (9 , searchable , SQL_C_SSHORT );
1525
- ES_TYPES_BINDCOL (10 , unsigned_attribute , SQL_C_SSHORT );
1526
- ES_TYPES_BINDCOL (11 , fixed_prec_scale , SQL_C_SSHORT );
1527
- ES_TYPES_BINDCOL (12 , auto_unique_value , SQL_C_SSHORT );
1528
- ES_TYPES_BINDCOL (13 , local_type_name , SQL_C_WCHAR );
1529
- ES_TYPES_BINDCOL (14 , minimum_scale , SQL_C_SSHORT );
1530
- ES_TYPES_BINDCOL (15 , maximum_scale , SQL_C_SSHORT );
1531
- ES_TYPES_BINDCOL (16 , sql_data_type , SQL_C_SSHORT );
1532
- ES_TYPES_BINDCOL (17 , sql_datetime_sub , SQL_C_SSHORT );
1533
- ES_TYPES_BINDCOL (18 , num_prec_radix , SQL_C_SLONG );
1534
- ES_TYPES_BINDCOL (19 , interval_precision , SQL_C_SSHORT );
1535
-
1536
- #undef ES_TYPES_BINDCOL
1638
+ if (! bind_types_cols (stmt , type_row )) {
1639
+ goto end ;
1640
+ }
1537
1641
1538
1642
/* fetch the results into the type_row array */
1539
1643
if (! SQL_SUCCEEDED (EsSQLFetch (stmt ))) {
@@ -1585,90 +1689,10 @@ static BOOL load_es_types(esodbc_dbc_st *dbc)
1585
1689
goto end ;
1586
1690
}
1587
1691
1588
- /* start pointer where the strings will be copied in */
1589
- pos = (SQLWCHAR * )& types [rows_fetched ];
1590
-
1591
- /* copy one integer member
1592
- * TODO: treat NULL case */
1593
- #define ES_TYPES_COPY_INT (_member ) \
1594
- do { \
1595
- if (type_row[i]._member ## _loi == SQL_NULL_DATA) { \
1596
- types[i]._member = 0; \
1597
- } else { \
1598
- types[i]._member = type_row[i]._member; \
1599
- } \
1600
- } while (0)
1601
- /* copy one wstr_st member
1602
- * Note: it'll shift NULLs to empty strings, as most of the API asks for
1603
- * empty strings if data is unavailable ("unkown"). */
1604
- #define ES_TYPES_COPY_WSTR (_wmember ) \
1605
- do { \
1606
- if (type_row[i]._wmember ## _loi == SQL_NULL_DATA) { \
1607
- types[i]._wmember.cnt = 0; \
1608
- types[i]._wmember.str = MK_WPTR(""); \
1609
- } else { \
1610
- types[i]._wmember.cnt = \
1611
- type_row[i]._wmember ## _loi / sizeof(SQLWCHAR); \
1612
- types[i]._wmember.str = pos; \
1613
- wmemcpy(types[i]._wmember.str, \
1614
- type_row[i]._wmember, types[i]._wmember.cnt + /*\0*/ 1 ); \
1615
- pos += types [i ]._wmember .cnt + /*\0*/ 1 ; \
1616
- } \
1617
- } while (0 )
1618
-
1619
- for (i = 0 ; i < rows_fetched ; i ++ ) {
1620
- /* copy data */
1621
- ES_TYPES_COPY_WSTR (type_name );
1622
- ES_TYPES_COPY_INT (data_type );
1623
- ES_TYPES_COPY_INT (column_size );
1624
- ES_TYPES_COPY_WSTR (literal_prefix );
1625
- ES_TYPES_COPY_WSTR (literal_suffix );
1626
- ES_TYPES_COPY_WSTR (create_params );
1627
- ES_TYPES_COPY_INT (nullable );
1628
- ES_TYPES_COPY_INT (case_sensitive );
1629
- ES_TYPES_COPY_INT (searchable );
1630
- ES_TYPES_COPY_INT (unsigned_attribute );
1631
- ES_TYPES_COPY_INT (fixed_prec_scale );
1632
- ES_TYPES_COPY_INT (auto_unique_value );
1633
- ES_TYPES_COPY_WSTR (local_type_name );
1634
- ES_TYPES_COPY_INT (minimum_scale );
1635
- ES_TYPES_COPY_INT (maximum_scale );
1636
- ES_TYPES_COPY_INT (sql_data_type );
1637
- ES_TYPES_COPY_INT (sql_datetime_sub );
1638
- ES_TYPES_COPY_INT (num_prec_radix );
1639
- ES_TYPES_COPY_INT (interval_precision );
1640
-
1641
- /* apply any needed fixes */
1642
-
1643
- /* warn if scales extremes are different */
1644
- if (types [i ].maximum_scale != types [i ].minimum_scale ) {
1645
- ERRH (dbc , "type `" LWPDL "` returned with non-equal max/min "
1646
- "scale: %d/%d." , LWSTR (& types [i ].type_name ),
1647
- types [i ].maximum_scale , types [i ].minimum_scale );
1648
- }
1649
-
1650
- /* resolve ES type to SQL C type */
1651
- types [i ].c_concise_type = type_elastic2csql (& types [i ].type_name );
1652
- if (types [i ].c_concise_type == SQL_UNKNOWN_TYPE ) {
1653
- /* ES version newer than driver's? */
1654
- ERRH (dbc , "failed to convert type name `" LWPDL "` to SQL C type." ,
1655
- LWSTR (& types [i ].type_name ));
1656
- goto end ;
1657
- }
1658
- /* set meta type */
1659
- types [i ].meta_type = concise_to_meta (types [i ].c_concise_type ,
1660
- /*C type -> AxD*/ DESC_TYPE_ARD );
1661
-
1662
- /* fix SQL_DATA_TYPE and SQL_DATETIME_SUB columns TODO: GH issue */
1663
- concise_to_type_code (types [i ].data_type , & types [i ].sql_data_type ,
1664
- & types [i ].sql_datetime_sub );
1665
-
1666
- set_display_size (types + i );
1692
+ if (! (pos = copy_types_rows (type_row , rows_fetched , types ))) {
1693
+ ERRH (dbc , "failed to process recieved ES/SQL data types." );
1694
+ goto end ;
1667
1695
}
1668
-
1669
- #undef ES_TYPES_COPY_INT
1670
- #undef ES_TYPES_COPY_WCHAR
1671
-
1672
1696
/* I didn't overrun the buffer */
1673
1697
assert ((char * )pos - (char * )(types + rows_fetched ) <=
1674
1698
(intptr_t )(strs_len ));
0 commit comments