1818#include < shellapi.h>
1919
2020namespace google ::cloud::odbc_bq_driver_internal {
21+ using google::cloud::odbc_bq_driver_internal::kDefaultMaxThreads ;
2122using google::cloud::odbc_bq_driver_internal::LanguageDialect;
2223using google::cloud::odbc_internal::StatusRecord;
2324
@@ -60,6 +61,7 @@ std::string AdvanceOptions::activation_threshold_checkbox_;
6061std::string AdvanceOptions::allow_large_results_;
6162std::string AdvanceOptions::use_default_large_results_;
6263std::string AdvanceOptions::encryption_type_ = kDefaultEncryptionType ;
64+ std::string AdvanceOptions::max_threads_ = std::to_string(kDefaultMaxThreads );
6365
6466std::string const kLanguageDialect = " SQLDialect" ;
6567std::string const kLargeResultsDatasetId = " LargeResultsDatasetId" ;
@@ -79,6 +81,7 @@ std::string const kAllowLargeResults = "AllowLargeResults";
7981std::string const kUseDefaultLargeResultsDataset =
8082 " UseDefaultLargeResultsDataset" ;
8183std::string const kEncryptionType = " EncryptionType" ;
84+ std::string const kMaxThreads = " MaxThreads" ;
8285
8386// Control dimensions and positions
8487int const kHeight = 20 ;
@@ -304,7 +307,7 @@ void AdvanceOptions::CreateSessionControls(HFONT h_font) {
304307 (enable_session_ == " 1" ) ? BST_CHECKED : BST_UNCHECKED );
305308
306309 HWND h_session_location_label =
307- CreateLabel (adv_hwnd, " Session location:" , kXAxis , kYAxis + 335 ,
310+ CreateLabel (adv_hwnd, " Session location:" , kXAxis , kYAxis + 340 ,
308311 kWidth * 2 + 30 , kHeight , WS_VISIBLE | SS_LEFT );
309312 SendMessage (h_session_location_label, WM_SETFONT , (WPARAM )h_font, TRUE );
310313 HWND h_session_location_edit =
@@ -321,20 +324,38 @@ void AdvanceOptions::CreateSessionControls(HFONT h_font) {
321324}
322325
323326void AdvanceOptions::CreateAdditionalControls (HFONT h_font) {
324- HWND h_variables_checkbox = CreateCheckBox (
325- adv_hwnd, " Use SQL_WVARCHAR instead of SQL_VARCHAR" , kXAxis , kYAxis + 360 ,
326- kWidth * 7 , kHeight , kIdcVariableCheckbox );
327- CheckDlgButton (adv_hwnd, kIdcVariableCheckbox ,
328- (use_wchar_ == " 1" ) ? BST_CHECKED : BST_UNCHECKED );
329- SendMessage (h_variables_checkbox, WM_SETFONT , (WPARAM )h_font, TRUE );
330- SetWindowSubclass (GetDlgItem (adv_hwnd, kIdcVariableCheckbox ),
331- CheckboxSubclassProc, 0 , 0 );
327+ // max threads
328+ HWND h_max_threads_label =
329+ CreateLabel (adv_hwnd, " Default number of Threads:" , kXAxis , kYAxis + 365 ,
330+ kWidth * 7 , kHeight , WS_VISIBLE | SS_LEFT );
331+ SendMessage (h_max_threads_label, WM_SETFONT , (WPARAM )h_font, TRUE );
332+ HWND h_max_threads_edit =
333+ CreateEditBox (adv_hwnd, kinputComboBoxXAxis, kYAxis + 360 , kEditBoxWidth ,
334+ kEditBoxHeight , kIdcMaxThreadsEdit );
335+ SendMessage (h_max_threads_edit, WM_SETFONT , (WPARAM )h_font, TRUE );
336+
337+ SetWindowSubclass (GetDlgItem (adv_hwnd, kIdcMaxThreadsEdit ), InputSubclassProc,
338+ 0 , 0 );
339+ SetWindowText (h_max_threads_edit, max_threads_.c_str ());
340+ SetWindowLongPtr (
341+ h_max_threads_edit, GWL_STYLE ,
342+ GetWindowLongPtr (h_max_threads_edit, GWL_STYLE ) | ES_RIGHT | ES_NUMBER );
343+
344+ // TODO(b/497725655): Enable UI feature after public release
345+ // HWND h_variables_checkbox = CreateCheckBox(
346+ // adv_hwnd, "Use SQL_WVARCHAR instead of SQL_VARCHAR", kXAxis, kYAxis +
347+ // 390, kWidth * 7, kHeight, kIdcVariableCheckbox);
348+ // CheckDlgButton(adv_hwnd, kIdcVariableCheckbox,
349+ // (use_wchar_ == "1") ? BST_CHECKED : BST_UNCHECKED);
350+ // SendMessage(h_variables_checkbox, WM_SETFONT, (WPARAM)h_font, TRUE);
351+ // SetWindowSubclass(GetDlgItem(adv_hwnd, kIdcVariableCheckbox),
352+ // CheckboxSubclassProc, 0, 0);
332353 HWND h_additional_projects_label =
333- CreateLabel (adv_hwnd, " Additional projects:" , kXAxis , kYAxis + 385 ,
354+ CreateLabel (adv_hwnd, " Additional projects:" , kXAxis , kYAxis + 390 ,
334355 kWidth * 5 , kHeight , WS_VISIBLE | SS_LEFT );
335356 SendMessage (h_additional_projects_label, WM_SETFONT , (WPARAM )h_font, TRUE );
336357 HWND h_additional_projects_edit =
337- CreateScrollableEditBox (adv_hwnd, kXAxis , kYAxis + 405 , kWidth + 380 ,
358+ CreateScrollableEditBox (adv_hwnd, kXAxis , kYAxis + 410 , kWidth + 380 ,
338359 kHeight + 32 , kIdcAdditionalProjectsEdit );
339360 SendMessage (h_additional_projects_edit, WM_SETFONT , (WPARAM )h_font, TRUE );
340361
@@ -343,11 +364,11 @@ void AdvanceOptions::CreateAdditionalControls(HFONT h_font) {
343364 InputSubclassProc, 0 , 0 );
344365
345366 HWND h_query_properties_label =
346- CreateLabel (adv_hwnd, " Query properties:" , kXAxis , kYAxis + 465 ,
367+ CreateLabel (adv_hwnd, " Query properties:" , kXAxis , kYAxis + 470 ,
347368 kWidth * 5 , kHeight , WS_VISIBLE | SS_LEFT );
348369 SendMessage (h_query_properties_label, WM_SETFONT , (WPARAM )h_font, TRUE );
349370 HWND h_query_properties_edit =
350- CreateScrollableEditBox (adv_hwnd, kXAxis , kYAxis + 485 , kWidth + 380 ,
371+ CreateScrollableEditBox (adv_hwnd, kXAxis , kYAxis + 485 , kWidth + 385 ,
351372 kHeight + 13 , kIdcQueryPropertiesEdit );
352373 SendMessage (h_query_properties_edit, WM_SETFONT , (WPARAM )h_font, TRUE );
353374
@@ -371,12 +392,12 @@ void AdvanceOptions::CreateAdditionalControls(HFONT h_font) {
371392}
372393
373394void AdvanceOptions::CreateButtons (HFONT h_font) {
374- HWND h_ok_button = CreateButton (adv_hwnd, " OK" , kOkButtonX + 2 , kButtonY + 10 ,
395+ HWND h_ok_button = CreateButton (adv_hwnd, " OK" , kOkButtonX + 2 , kButtonY + 15 ,
375396 kButtonWidth , kButtonHeight , kIdcOKButton );
376397 SendMessage (h_ok_button, WM_SETFONT , (WPARAM )h_font, TRUE );
377398
378399 HWND h_cancel_button =
379- CreateButton (adv_hwnd, " Cancel" , kCancelButtonX , kButtonY + 10 ,
400+ CreateButton (adv_hwnd, " Cancel" , kCancelButtonX , kButtonY + 15 ,
380401 kButtonWidth , kButtonHeight , kIdcCancelButton );
381402 SendMessage (h_cancel_button, WM_SETFONT , (WPARAM )h_font, TRUE );
382403}
@@ -467,8 +488,16 @@ LRESULT CALLBACK AdvanceOptions::AdvanceOptProc(HWND hwnd, UINT u_msg,
467488 char temp_expiration_buffer[256 ] = {0 };
468489 GetWindowText (h_temp_expiration_edit, temp_expiration_buffer,
469490 sizeof (temp_expiration_buffer));
470- temp_expiration_ = temp_expiration_buffer;
471-
491+ if (isValidUint32 (temp_expiration_buffer)) {
492+ temp_expiration_ = temp_expiration_buffer;
493+ } else {
494+ auto err_msg =
495+ " Invalid temporary table expiry: Valid values are in range "
496+ " [0," +
497+ std::to_string (UINT32_MAX ) + " ]" ;
498+ ShowErrorWindow (hwnd, err_msg);
499+ return true ;
500+ }
472501 HWND h_encryption_key_edit = GetDlgItem (hwnd, kIdcEncryptionKeyEdit );
473502 char encryption_key_buffer[256 ] = {0 };
474503 GetWindowText (h_encryption_key_edit, encryption_key_buffer,
@@ -479,14 +508,28 @@ LRESULT CALLBACK AdvanceOptions::AdvanceOptProc(HWND hwnd, UINT u_msg,
479508 char rows_per_block_buffer[256 ] = {0 };
480509 GetWindowText (h_rows_per_block_edit, rows_per_block_buffer,
481510 sizeof (rows_per_block_buffer));
482- rows_per_block_ = rows_per_block_buffer;
483-
511+ if (isValidUint32 (rows_per_block_buffer)) {
512+ rows_per_block_ = rows_per_block_buffer;
513+ } else {
514+ auto err_msg =
515+ " Invalid rows per block: Valid values are in range [0," +
516+ std::to_string (UINT32_MAX ) + " ]" ;
517+ ShowErrorWindow (hwnd, err_msg);
518+ return true ;
519+ }
484520 HWND h_default_string_edit = GetDlgItem (hwnd, kIdcDefaultStringEdit );
485521 char default_string_buffer[256 ] = {0 };
486522 GetWindowText (h_default_string_edit, default_string_buffer,
487523 sizeof (default_string_buffer));
488- default_string_length_ = default_string_buffer;
489-
524+ if (isValidUint32 (default_string_buffer)) {
525+ default_string_length_ = default_string_buffer;
526+ } else {
527+ auto err_msg =
528+ " Invalid default string length: Valid values are in range [0," +
529+ std::to_string (UINT32_MAX ) + " ]" ;
530+ ShowErrorWindow (hwnd, err_msg);
531+ return true ;
532+ }
490533 HWND h_encryption_combo_box =
491534 GetDlgItem (hwnd, kIdcEncryptionKeyComboBox );
492535 char encryption_type_buffer[256 ] = {0 };
@@ -509,6 +552,19 @@ LRESULT CALLBACK AdvanceOptions::AdvanceOptProc(HWND hwnd, UINT u_msg,
509552 session_location_ = " " ;
510553 }
511554
555+ HWND h_max_threads_edit = GetDlgItem (hwnd, kIdcMaxThreadsEdit );
556+ char max_threads_buff[256 ] = {0 };
557+ GetWindowText (h_max_threads_edit, max_threads_buff,
558+ sizeof (max_threads_buff));
559+ if (isValidUint32 (max_threads_buff)) {
560+ max_threads_ = max_threads_buff;
561+ } else {
562+ std::string err_msg =
563+ " Invalid number of max threads: Valid values are in range [0," +
564+ std::to_string (UINT32_MAX ) + " ]" ;
565+ ShowErrorWindow (hwnd, err_msg);
566+ return true ;
567+ }
512568 HWND h_additional_projects_edit =
513569 GetDlgItem (hwnd, kIdcAdditionalProjectsEdit );
514570 char additional_projects_buffer[1024 ] = {0 };
@@ -540,11 +596,11 @@ LRESULT CALLBACK AdvanceOptions::AdvanceOptProc(HWND hwnd, UINT u_msg,
540596 GetWindowText (h_activation_threshold, activation_threshold_buffer,
541597 sizeof (activation_threshold_buffer));
542598 activation_threshold_ = activation_threshold_buffer;
543-
544- use_wchar_ =
545- (IsDlgButtonChecked (hwnd, kIdcVariableCheckbox ) == BST_CHECKED )
546- ? " 1"
547- : " 0" ;
599+ // TODO(b/497725655): Enable UI feature after public release
600+ // use_wchar_ =
601+ // (IsDlgButtonChecked(hwnd, kIdcVariableCheckbox) == BST_CHECKED)
602+ // ? "1"
603+ // : "0";
548604
549605 enable_session_ =
550606 (IsDlgButtonChecked (hwnd, kIdcEnableSessionCheckbox ) ==
@@ -685,12 +741,14 @@ void AdvanceOptions::SetValues(Section const& attribute_map) {
685741 GetValueOrDefault (attribute_map, kDefaultStringColumnLength );
686742 temp_expiration_ =
687743 GetValueOrDefault (attribute_map, kLargeResultsTempTableExpirationTime );
744+ max_threads_ = GetValueOrDefault (attribute_map, kMaxThreads );
688745 session_location_ = GetValueOrDefault (attribute_map, kSessionLocation );
689746 additional_projects_ = GetValueOrDefault (attribute_map, kAdditionalProjects );
690747 query_properties_ = GetValueOrDefault (attribute_map, kQueryProperties );
691748 activation_threshold_ =
692749 GetValueOrDefault (attribute_map, kActivationThreshold );
693- use_wchar_ = GetValueOrDefault (attribute_map, kUseWChar );
750+ // TODO(b/497725655): Enable UI feature after public release
751+ // use_wchar_ = GetValueOrDefault(attribute_map, kUseWChar);
694752 enable_session_ = GetValueOrDefault (attribute_map, kSessionLocation );
695753 activation_threshold_checkbox_ =
696754 GetValueOrDefault (attribute_map, kHTAPIActivationThresholdCheck );
@@ -707,11 +765,12 @@ void AdvanceOptions::ResetToDefaults() {
707765 encryption_key_.clear ();
708766 rows_per_block_ = kDefaultRowsPerBlock ;
709767 default_string_length_ = kDefaultStringLength ;
768+ max_threads_ = std::to_string (kDefaultMaxThreads );
710769 session_location_.clear ();
711770 additional_projects_.clear ();
712771 query_properties_.clear ();
713772 activation_threshold_.clear ();
714- use_wchar_.clear ();
773+ // use_wchar_.clear();
715774 enable_session_.clear ();
716775 activation_threshold_checkbox_.clear ();
717776 allow_large_results_.clear ();
@@ -739,7 +798,7 @@ void AdvanceOptions::Show(HWND hwnd) {
739798 RegisterClass (&wc_adv);
740799
741800 int window_width = 462 ;
742- int window_height = 618 ;
801+ int window_height = 620 ;
743802 int screen_width = GetSystemMetrics (SM_CXSCREEN );
744803 int screen_height = GetSystemMetrics (SM_CYSCREEN );
745804 int x_pos = (screen_width - window_width) / 2 ;
0 commit comments