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