SELECT SQL - tdslite.h

Good afternoon.
I need to read data from a table in a SQL server. I am using an Arduino Mega with a Sahild Ethernet. I can connect to the SQL and I can read the data from the table. But I don't know what I'm reading. Do not read the first column. I am actually recovering the data in a strange way.
I document what I'm doing.

#include <Ethernet.h>
#include <tdslite.h>

// Serial output uses ~175 bytes of SRAM space
// and ~840 bytes of program memory.
#define SKETCH_ENABLE_SERIAL_OUTPUT

#if defined SKETCH_ENABLE_SERIAL_OUTPUT

#define SERIAL_PRINTF_PROGMEM(FMTPM, ...)                                                          \
    char buf [64] = {};                                                                            \
    snprintf_P(buf, sizeof(buf), FMTPM, ##__VA_ARGS__);                                            \
    Serial.print(buf);

#define SERIAL_PRINTF(FMTSTR, ...)                                                                 \
    [&]() {                                                                                        \
        /* Save format string into program */                                                      \
        /* memory to save flash space */                                                           \
        static const char __fmtpm [] PROGMEM = FMTSTR;                                             \
        SERIAL_PRINTF_PROGMEM(__fmtpm, ##__VA_ARGS__)                                              \
    }()

#define SERIAL_PRINTLNF_PROGMEM(FMTPM, ...)                                                        \
    SERIAL_PRINTF_PROGMEM(FMTPM, ##__VA_ARGS__)                                                    \
    Serial.println("");                                                                            \
    Serial.flush()

#define SERIAL_PRINTLNF(FMTSTR, ...)                                                               \
    SERIAL_PRINTF(FMTSTR, ##__VA_ARGS__);                                                          \
    Serial.println("");                                                                            \
    Serial.flush()

#define SERIAL_PRINT_U16_AS_MB(U16SPAN)                                                            \
    [](tdsl::u16char_view v) {                                                                     \
        for (const auto ch : v) {                                                                  \
            Serial.print(static_cast<char>(ch));                                                   \
        }                                                                                          \
    }(U16SPAN)
#else
#define SERIAL_PRINTF_PROGMEM(FMTPM, ...)
#define SERIAL_PRINTF(FMTSTR, ...)
#define SERIAL_PRINTLNF_PROGMEM(FMTPM, ...)
#define SERIAL_PRINTLNF(FMTSTR, ...)
#define SERIAL_PRINT_U16_AS_MB(U16SPAN)
#endif

// --------------------------------------------------------------------------------

/**
 * The network buffer.
 *
 * The library will use this buffer for network I/O.
 *
 * The buffer must be at least 512 bytes in size.
 * In order to have some headroom for fragmentation
 * it is recommended to allocate 768 bytes at least.
 *
 * The actual size need for network buffer is depends
 * on your use case.
 *
 *
 * TODO: Extend this section
 */
tdsl::uint8_t net_buf [768] = {};

// --------------------------------------------------------------------------------

/**
 * The tdslite driver object.
 *
 * tdsl::arduino_driver class is a templated type
 * where the template argument is the TCP client
 * implementation compatible with Arduino's
 * EthernetClient interface.
 *
 * The client will be initialized internally.
 */
tdsl::arduino_driver<EthernetClient> driver{net_buf};

// --------------------------------------------------------------------------------

/**
 * MAC address for the ethernet interface
 */
 byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x04};
// --------------------------------------------------------------------------------

/**
 * The setup function initializes Serial output,
 * Ethernet interface, tdslite library and then
 * the database tables.
 */
void setup() {
Serial.begin(9600);
  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin(mac) == 0) 
    {
    Serial.println("Failed to configure Ethernet using DHCP");
    if (Ethernet.hardwareStatus() == EthernetNoHardware) 
      {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      } 
    else if (Ethernet.linkStatus() == LinkOFF) 
    {
      Serial.println("Ethernet cable is not connected.");
    }
    // no point in carrying on, so do nothing forevermore:
    while (true) 
      {
      delay(1);
      }
    }
  // print your local IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());

    //////////////////////////
    // Initialize ethernet interface
    //////////////////////////

    // The reason we're not using DHCP here is, this is
    // a minimal example with absolute minimum space
    // requirements, so the code can work on boards with
    // tight memory constraints (i.e. Arduino Uno/Nano)
    //
    // DHCP requires UDP, UDP requires extra space.
    // We're not using DHCP here to save some program
    // memory and SRAM space.



    // Check if *any* ethernet hardware is detected.
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
        SERIAL_PRINTLNF("Error: No ethernet hardware detected!");
        // Ethernet shield not detected
        while (true) {
            delay(1000);
        }
    }

    //*****************
    // Initialize tdslite
  
    decltype(driver)::progmem_connection_parameters params;
    // Server's hostname or IP address.
    params.server_name = TDSL_PMEMSTR("x.x.x.x"); // WL
    // SQL server port number
    params.port        = 3333; // default port is 1433
    // SQL server login user
    params.user_name   = TDSL_PMEMSTR("cuirplan");
    // SQL server login user password
    params.password    = TDSL_PMEMSTR("pwr");
    // Client name(optional)
    params.client_name = TDSL_PMEMSTR("arduino mega");
    // App name(optional)
    params.app_name    = TDSL_PMEMSTR("sketch");
    // Database name(optional)
    params.db_name     = TDSL_PMEMSTR("PROVES_CuirPlan");
    // TDS packet size
    // Recommendation: Half of the network buffer.
    // This is the PDU size that TDS protocol will use.
    // Given that the example has 768 bytes of network buffer space,
    // we set this to 512 to allow some headroom for fragmentation.
    params.packet_size = {512};

    SERIAL_PRINTLNF("Initializing tdslite");

    // Try to connect with given parameters. If connection succeeds,
    // the `result` will be e_driver_error_code::success. Otherwise,
    // the connection attempt has failed.
    auto result = driver.connect(params);

    if (not(decltype(driver)::e_driver_error_code::success == result)) {
        SERIAL_PRINTLNF("Error: Database connection failed!");
        // Database connection failed.
        while (true) {
            delay(1000);
        }
    }

    //////////////////////////
    // Initialize the database
    //////////////////////////

    driver.execute_query(TDSL_PMEMSTR("CREATE TABLE #example_table(a varchar(12), b int);"));
}

// --------------------------------------------------------------------------------

/**
 * How many times the loop function has
 * been invoked.
 */
static int loop_counter = {0};

// --------------------------------------------------------------------------------

/**
 * Handle row data coming from tdsl driver
 *
 * @param [in] u user pointer (table_context)
 * @param [in] colmd Column metadata
 * @param [in] row Row information
 */
static void row_callback(void * u, const tdsl::tds_colmetadata_token & colmd,
                         const tdsl::tdsl_row & row) 
  {
  //SERIAL_PRINTLNF("row: %d %d %d %d %d", row [0].as<tdsl::int32_t>(),
  SERIAL_PRINTLNF("row: %.4s %d", row [0].as<tdsl::char_view>().data(),
                    row [1].as<tdsl::int32_t>());                    
  }

// --------------------------------------------------------------------------------

/**
 * The loop function executes INSERT query every
 * 1 second, and SELECT query every 10 seconds.
 */
void loop() 
  {

  auto query{TDSL_PMEMSTR("SELECT * FROM prjMagatzemLeds")};
  //auto query{TDSL_PMEMSTR("SELECT * FROM prjComptadors")};
  //auto query{TDSL_PMEMSTR("SELECT * FROM prjComptadors WHERE idComptador='3'")};
  SERIAL_PRINTF("Executing query: ");
  SERIAL_PRINTLNF_PROGMEM(query.raw_data());
  // We're using the row
  auto result = driver.execute_query(query, row_callback);
  SERIAL_PRINTLNF("Rows affected: %d", result.affected_rows);
 
  
  delay(10000);
  }

Info BD SQL:

SQL

Lectures:
SQLRetorn

As you can see, the first column is not read.
I also think that the system I use is not correct.

static void row_callback(void * u, const tdsl::tds_colmetadata_token & colmd,
                         const tdsl::tdsl_row & row) 
  {
  //SERIAL_PRINTLNF("row: %d %d %d %d %d", row [0].as<tdsl::int32_t>(),
  SERIAL_PRINTLNF("row: %.4s %d", row [0].as<tdsl::char_view>().data(),
                    row [1].as<tdsl::int32_t>());                    
  }

Thanks for the help.

I attach the structure of the BD. I can't read the first field. In tales of reading "01;05;00;02;00;00;6C;0A;" i read "0".
But I think I have the field well declared:

row [0].as<tdsl::char_view>().data()

I am attaching an image of the structure of the table.

SQLEstructura

If I change the table structure it works.

SQLEstructura2

Result:

xecuting query: SELECT * FROM prjMagatzemLeds
row: 01;05;00;02;00;00;6C;0A; 11
row: 01;05;00;02;FF;00;2D;FA; 22
row: 01;05;00;00;FF;00;8C;3A;! 33
row: 01;05;00;00;00;00;CD;CA;, 44
Rows affected: 4

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.