28#define FREE(x) { if (x) free(x); (x) = NULL; }
83static const char *sql_type_pgsql[] = {
98 "xxxINVALIDxxxSTRUCT",
118 "xxxINVALIDxxxARRAY",
119 "xxxINVALIDxxxSTRUCT",
146 for (
int tid=0; tid<15; tid++)
149 printf(
"sql2midasType: Cannot convert SQL data type \'%s\' to a MIDAS data type!\n",
name);
166 if (tid==
TID_FLOAT && strcmp(sqlType,
"double")==0)
171 if (tid==
TID_UINT8 && strcmp(sqlType,
"tinyint")==0)
176 if (tid==
TID_UINT16 && strcmp(sqlType,
"tinyint")==0)
193 virtual int Exec(
const char* sql) = 0;
199 virtual int ListColumns(
const char* table, std::vector<std::string> *plist) = 0;
240 filename =
"/dev/fd/1";
241 fp = fopen(filename,
"w");
250 fprintf(
fp,
"%s\n", sql);
283#define DWORD DWORD_xxx
321 int ListTables(std::vector<std::string> *plist);
322 int ListColumns(
const char* table_name, std::vector<std::string> *plist);
324 int Exec(
const char* sql);
333 void ReportErrors(
const char* from,
const char* sqlfunc,
int status);
339 fIsConnected =
false;
348int SqlODBC::Connect(
const char* dsn)
355 int status = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &fEnv);
357 if (!SQL_SUCCEEDED(
status)) {
358 cm_msg(
MERROR,
"SqlODBC::Connect",
"SQLAllocHandle(SQL_HANDLE_ENV) error %d",
status);
362 status = SQLSetEnvAttr(fEnv,
363 SQL_ATTR_ODBC_VERSION,
366 if (!SQL_SUCCEEDED(
status)) {
368 SQLFreeHandle(SQL_HANDLE_ENV, fEnv);
372 status = SQLAllocHandle(SQL_HANDLE_DBC, fEnv, &fDB);
373 if (!SQL_SUCCEEDED(
status)) {
374 cm_msg(
MERROR,
"SqlODBC::Connect",
"SQLAllocHandle(SQL_HANDLE_DBC) error %d",
status);
375 SQLFreeHandle(SQL_HANDLE_ENV, fEnv);
379 SQLSetConnectAttr(fDB, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);
385 status = SQLConnect(fDB, (SQLCHAR*) dsn, SQL_NTS,
386 (SQLCHAR*)
"xxx", SQL_NTS,
387 (SQLCHAR*)
"", SQL_NTS);
394 status = SQLConnect(fDB, (SQLCHAR*) dsn, SQL_NTS,
395 (SQLCHAR*) NULL, SQL_NTS,
396 (SQLCHAR*) NULL, SQL_NTS);
399 if ((
status != SQL_SUCCESS) && (
status != SQL_SUCCESS_WITH_INFO)) {
401 SQLSMALLINT V_OD_mlen;
402 SQLCHAR V_OD_stat[10];
403 SQLCHAR V_OD_msg[200];
405 SQLGetDiagRec(SQL_HANDLE_DBC, fDB, 1, V_OD_stat, &V_OD_err, V_OD_msg, 100, &V_OD_mlen);
406 cm_msg(
MERROR,
"SqlODBC::Connect",
"SQLConnect() error %d, %s (%d)",
status, V_OD_msg,V_OD_err);
407 SQLFreeHandle(SQL_HANDLE_ENV, fEnv);
411 SQLAllocHandle(SQL_HANDLE_STMT, fDB, &fStmt);
414 cm_msg(
MINFO,
"SqlODBC::Connect",
"Connected to ODBC database DSN \'%s\'", dsn);
421int SqlODBC::Disconnect()
428 SQLFreeHandle(SQL_HANDLE_DBC, fDB);
429 SQLFreeHandle(SQL_HANDLE_STMT, fStmt);
430 SQLFreeHandle(SQL_HANDLE_ENV, fEnv);
432 fIsConnected =
false;
437bool SqlODBC::IsConnected()
442void SqlODBC::ReportErrors(
const char* from,
const char* sqlfunc,
int status)
445 printf(
"%s: %s error %d\n", from, sqlfunc,
status);
447 for (
int i=1; ;
i++) {
453 status = SQLGetDiagRec(SQL_HANDLE_STMT,
462 if (
status == SQL_NO_DATA)
465 if (!SQL_SUCCEEDED(
status)) {
472 if (1 || (error == 2006) ) {
474 printf(
"%s: %s warning: state: \'%s\', message: \'%s\', native error: %d\n", from, sqlfunc,
state,
message, (
int)error);
475 cm_msg(
MINFO, from,
"%s warning: state: \'%s\', message: \'%s\', native error: %d", sqlfunc,
state,
message, (
int)error);
476 }
else if (1 || ((error != 1060) && (error != 1050))) {
478 printf(
"%s: %s error: state: \'%s\', message: \'%s\', native error: %d\n", from, sqlfunc,
state,
message, (
int)error);
479 cm_msg(
MERROR, from,
"%s error: state: \'%s\', message: \'%s\', native error: %d", sqlfunc,
state,
message, (
int)error);
484int SqlODBC::DecodeError()
491 for (
int i=1; ;
i++) {
499 int status = SQLGetDiagRec(SQL_HANDLE_STMT,
508 if (
status == SQL_NO_DATA)
519int SqlODBC::ListTables(std::vector<std::string> *plist)
524 for (
int i=0;
i<2;
i++) {
526 printf(
"SqlODBC::ListTables!\n");
529 int status = SQLTables(fStmt, NULL, 0, NULL, 0, NULL, 0, (SQLCHAR*)
"TABLE", SQL_NTS);
531 if (SQL_SUCCEEDED(
status))
535 printf(
"SqlODBC::ListTables: SQLTables() error %d\n",
status);
537 ReportErrors(
"SqlODBC::ListTables",
"SQLTables()",
status);
547 cm_msg(
MINFO,
"SqlODBC::ListTables",
"Reconnecting to ODBC database DSN \'%s\'", fDSN.c_str());
550 std::string dsn = fDSN;
552 status = Connect(dsn.c_str());
555 cm_msg(
MERROR,
"SqlODBC::ListTables",
"Cannot reconnect to ODBC database DSN \'%s\', status %d. Database is down?", fDSN.c_str(),
status);
559 cm_msg(
MINFO,
"SqlODBC::ListTables",
"Reconnected to ODBC database DSN \'%s\'", fDSN.c_str());
562 int ncols = GetNumColumns();
563 int nrows = GetNumRows();
565 if (ncols <= 0 || nrows <= 0) {
566 cm_msg(
MERROR,
"SqlODBC::ListTables",
"Error: SQLTables() returned unexpected number of columns %d or number of rows %d", ncols, nrows);
576 printf(
"row %d: ", row);
577 for (
int i=1;
i<=ncols;
i++) {
578 const char* s = GetColumn(
i);
585 plist->push_back(GetColumn(3));
593int SqlODBC::ListColumns(
const char* table, std::vector<std::string> *plist)
598 for (
int i=0;
i<2;
i++) {
600 printf(
"SqlODBC::ListColumns for table \'%s\'\n", table);
603 int status = SQLColumns(fStmt, NULL, 0, NULL, 0, (SQLCHAR*)table, SQL_NTS, NULL, 0);
605 if (SQL_SUCCEEDED(
status))
609 printf(
"SqlODBC::ListColumns: SQLColumns(%s) error %d\n", table,
status);
611 ReportErrors(
"SqlODBC::ListColumns",
"SQLColumns()",
status);
621 cm_msg(
MINFO,
"SqlODBC::ListColumns",
"Reconnecting to ODBC database DSN \'%s\'", fDSN.c_str());
624 std::string dsn = fDSN;
626 status = Connect(dsn.c_str());
629 cm_msg(
MERROR,
"SqlODBC::ListColumns",
"Cannot reconnect to ODBC database DSN \'%s\', status %d. Database is down?", fDSN.c_str(),
status);
633 cm_msg(
MINFO,
"SqlODBC::ListColumns",
"Reconnected to ODBC database DSN \'%s\'", fDSN.c_str());
636 int ncols = GetNumColumns();
637 int nrows = GetNumRows();
640 cm_msg(
MERROR,
"SqlODBC::ListColumns",
"Error: SQLColumns(\'%s\') returned unexpected number of columns %d or number of rows %d", table, ncols, nrows);
652 printf(
"row %d: ", row);
653 for (
int i=1;
i<=ncols;
i++) {
654 const char* s = GetColumn(
i);
661 plist->push_back(GetColumn(4));
662 plist->push_back(GetColumn(6));
670int SqlODBC::Exec(
const char* sql)
682 for (
int i=0;
i<2;
i++) {
684 printf(
"SqlODBC::Exec: %s\n", sql);
686 status = SQLExecDirect(fStmt,(SQLCHAR*)sql,SQL_NTS);
688 if (SQL_SUCCEEDED(
status)) {
693 printf(
"SqlODBC::Exec: SQLExecDirect() error %d: SQL command: \"%s\"\n",
status, sql);
695 ReportErrors(
"SqlODBC::Exec",
"SQLExecDirect()",
status);
705 cm_msg(
MINFO,
"SqlODBC::Exec",
"Reconnecting to ODBC database DSN \'%s\'", fDSN.c_str());
708 std::string dsn = fDSN;
710 status = Connect(dsn.c_str());
713 cm_msg(
MERROR,
"SqlODBC::Exec",
"Cannot reconnect to ODBC database DSN \'%s\', status %d. Database is down?", fDSN.c_str(),
status);
717 cm_msg(
MINFO,
"SqlODBC::Exec",
"Reconnected to ODBC database DSN \'%s\'", fDSN.c_str());
723int SqlODBC::GetNumRows()
727 int status = SQLRowCount(fStmt, &nrows);
728 if (!SQL_SUCCEEDED(
status)) {
729 ReportErrors(
"SqlODBC::GetNumRow",
"SQLRowCount()",
status);
735int SqlODBC::GetNumColumns()
737 SQLSMALLINT ncols = 0;
739 int status = SQLNumResultCols(fStmt, &ncols);
740 if (!SQL_SUCCEEDED(
status)) {
741 ReportErrors(
"SqlODBC::GetNumColumns",
"SQLNumResultCols()",
status);
749 int status = SQLFetch(fStmt);
751 if (
status == SQL_NO_DATA)
754 if (!SQL_SUCCEEDED(
status)) {
755 ReportErrors(
"SqlODBC::Fetch",
"SQLFetch()",
status);
764 int status = SQLCloseCursor(fStmt);
765 if (!SQL_SUCCEEDED(
status)) {
766 ReportErrors(
"SqlODBC::Done",
"SQLCloseCursor()",
status);
772const char* SqlODBC::GetColumn(
int icol)
774 static char buf[1024];
776 int status = SQLGetData(fStmt, icol, SQL_C_CHAR, buf,
sizeof(buf), &indicator);
778 if (!SQL_SUCCEEDED(
status)) {
782 if (indicator == SQL_NULL_DATA)
826 for (
int i=0;
i<ntags;
i++)
834 int n =
e->tags.size();
842 for (
int i=0;
i<
n;
i++) {
843 const Tag*t = &
e->tags[
i];
847 void* ptr = (
void*)(buf+
offset);
851 for (
int j=0;
j<arraySize;
j++) {
868 sprintf(s,
"unknownType%d", t->
tag.
type);
871 sprintf(s,
"%u",((
unsigned char*)ptr)[
j]);
874 sprintf(s,
"%d",((
signed char*)ptr)[
j]);
877 sprintf(s,
"\'%c\'",((
char*)ptr)[
j]);
880 sprintf(s,
"%u",((
unsigned short*)ptr)[
j]);
883 sprintf(s,
"%d",((
signed short*)ptr)[
j]);
886 sprintf(s,
"%u",((
unsigned int*)ptr)[
j]);
889 sprintf(s,
"%d",((
int*)ptr)[
j]);
892 sprintf(s,
"%u",((
unsigned int*)ptr)[
j]);
895 sprintf(s,
"\'%.8g\'",((
float*)ptr)[
j]);
898 sprintf(s,
"\'%.16g\'",((
double*)ptr)[
j]);
909 localtime_r(&t, &tms);
911 strftime(s,
sizeof(s)-1,
"%Y-%m-%d %H:%M:%S.0",&tms);
914 sprintf(sss,
"INSERT INTO %s (_t_time, _i_time%s) VALUES (\'%s\', \'%d\'%s);",
915 e->table_name.c_str(),
936 for (
int i=0; s[
i]!=0;
i++) {
938 if (isalpha(
c) || isdigit(
c))
959 std::vector<IndexEntryTag>
tags;
966static void PrintIndex()
971 printf(
"entry %d: [%s] [%s], time %d, tags\n",
i,
e->event_name.c_str(),
e->table_name.c_str(),
e->timestamp);
973 for (
unsigned j=0;
j<
e->tags.size();
j++)
974 printf(
" tag %d: [%s] [%s], time %d\n",
j,
e->tags[
j].tag_name.c_str(),
e->tags[
j].column_name.c_str(),
e->tags[
j].timestamp);
999 for (
unsigned i=0;
i<ie->
tags.size();
i++)
1001 return &ie->
tags[
i];
1008 for (
unsigned i=0;
i<ie->
tags.size();
i++)
1010 return &ie->
tags[
i];
1023 printf(
"ReadIndex [%s]\n", event_name);
1032 printf(
"ReadIndex: reading index for event [%s]\n", event_name);
1039 sprintf(cmd,
"SELECT event_name, table_name, tag_name, column_name, itimestamp FROM _history_index where event_name=\'%s\';", event_name);
1041 sprintf(cmd,
"SELECT event_name, table_name, tag_name, column_name, itimestamp FROM _history_index;");
1051 printf(
"ReadIndex: event %s, Read status %d, nrows: %d\n",
1072 printf(
"ReadIndex: event %s, nrows: %d, ncols: %d\n",
1088 std::string xevent_name = sql->
GetColumn(1);
1092 std::string xtable_name = p;
1093 std::string xtimestamp = sql->
GetColumn(5);
1094 int timestamp = atoi(xtimestamp.c_str());
1115 std::string xtag_name = p;
1116 std::string xcolumn_name = sql->
GetColumn(4);
1117 std::string xtimestamp = sql->
GetColumn(5);
1118 int timestamp = atoi(xtimestamp.c_str());
1129 for (
unsigned j=0;
j<ie->
tags.size();
j++)
1130 if (ie->
tags[
j].tag_name == xtag_name) {
1131 if (timestamp > ie->
tags[
j].timestamp) {
1132 ie->
tags[
j].timestamp = timestamp;
1133 ie->
tags[
j].column_name = xcolumn_name;
1144 ie->
tags.push_back(it);
1157 if (event_name == NULL)
1211 printf(
"hs_connect %s!\n", connect_string);
1224 printf(
"hs_connect: connecting to SQL database \'%s\'\n",
fConnectString.c_str());
1230 std::vector<std::string> tables;
1236 for (
unsigned i=0;
i<tables.size();
i++) {
1237 if (tables[
i] ==
"_history_index") {
1249 printf(
"hs_disconnect!\n");
1261 printf(
"Reconnect to SQL database!\n");
1279 printf(
"hs_clear_cache!\n");
1302 printf(
"XReadIndex!\n");
1304 std::vector<std::string> tables;
1310 for (
unsigned i=0;
i<tables.size();
i++) {
1311 if (tables[
i] ==
"_history_index")
1325 std::vector<std::string> columns;
1331 for (
unsigned int j=0;
j<columns.size();
j+=2) {
1332 if (columns[
j] ==
"_t_time")
1334 if (columns[
j] ==
"_i_time")
1342 ie->
tags.push_back(t);
1362 printf(
"define event [%s] with %d tags:\n", event_name, ntags);
1367 for (
unsigned int i=0;
i<
fEvents.size();
i++)
1369 if (
fEvents[
i]->event_name == event_name) {
1371 printf(
"deleting exising event %s\n", event_name);
1378 e->event_name = event_name;
1382 sprintf(buf,
"CREATE TABLE _history_index (event_name VARCHAR(256) NOT NULL, table_name VARCHAR(256), tag_name VARCHAR(256), column_name VARCHAR(256), itimestamp INTEGER NOT NULL);");
1402 sprintf(sss,
"INSERT INTO _history_index (event_name, table_name, itimestamp) VALUES (\'%s\', \'%s\', \'%.0f\');",
1416 cm_msg(
MERROR,
"hs_define_event",
"could not add event name to SQL history index table, see messages");
1423 bool create_event =
false;
1426 for (
int i=0;
i<ntags;
i++) {
1427 for (
unsigned int j=0;
j<tags[
i].
n_data;
j++) {
1428 std::string tagname = tags[
i].
name;
1431 if (tags[
i].n_data > 1) {
1433 sprintf(s,
"[%d]",
j);
1436 sprintf(s,
"_%d",
j);
1447 for (
unsigned i=0;
i<
e->tags.size();
i++) {
1448 if (colname ==
e->tags[
i].column_name) {
1459 sprintf(s,
"_%d", rand());
1466 sprintf(sss,
"INSERT INTO _history_index (event_name, tag_name, column_name, itimestamp) VALUES (\'%s\', \'%s\', \'%s\', \'%.0f\');",
1485 cm_msg(
MERROR,
"hs_define_event",
"could not add event tags to SQL history index table, see messages");
1495 e->tags.push_back(t);
1501 std::vector<std::string> columns;
1507 if (columns.size() <= 0)
1508 create_event =
true;
1510 for (
unsigned i=0;
i<
e->tags.size();
i++) {
1512 for (
unsigned j=
i+1;
j<
e->tags.size();
j++)
1513 if (
e->tags[
i].column_name ==
e->tags[
j].column_name) {
1514 cm_msg(
MERROR,
"hs_define_event",
"Error: History event \'%s\': Duplicated column name \'%s\' from tags %d \'%s\' and %d \'%s\'", event_name,
e->tags[
i].column_name.c_str(),
i,
e->tags[
i].tag.name,
j,
e->tags[
j].tag.name);
1521 for (
size_t j=0;
j<columns.size();
j+=2) {
1522 if (
e->tags[
i].column_name == columns[
j]) {
1527 cm_msg(
MERROR,
"hs_define_event",
"Error: History event \'%s\': Incompatible data type for tag \'%s\' type \'%s\', SQL column \'%s\' type \'%s\'", event_name,
e->tags[
i].tag.name,
midasTypeName(
e->tags[
i].tag.type), columns[
j].c_str(), columns[
j+1].c_str());
1539 e->tags[
i].create =
true;
1545 sprintf(buf,
"CREATE TABLE %s (_t_time TIMESTAMP NOT NULL, _i_time INTEGER NOT NULL, INDEX (_i_time), INDEX (_t_time));",
e->table_name.c_str());
1553 for (
size_t i=0;
i<
e->tags.size();
i++)
1554 if (
e->tags[
i].create) {
1557 sprintf(buf,
"ALTER TABLE %s ADD COLUMN %s %s;",
1558 e->table_name.c_str(),
1559 e->tags[
i].column_name.c_str(),
1571 for (
unsigned int i=0;
i<
fEvents.size();
i++)
1585 int hs_write_event(
const char* event_name, time_t timestamp,
int buffer_size,
const char* buffer)
1588 printf(
"hs_write_event: write event \'%s\', time %d, size %d\n", event_name, (
int)timestamp, buffer_size);
1593 time_t now = time(NULL);
1632 if (
fEvents[
i]->event_name == event_name) {
1671 printf(
"hs_flush_buffers!\n");
1682 printf(
"hs_get_events!\n");
1687 printf(
"hs_get_events: reading event names!\n");
1691 std::vector<std::string> tables;
1696 for (
unsigned i=0;
i<tables.size();
i++) {
1697 if (tables[
i] ==
"_history_index")
1719 int hs_get_tags(
const char* event_name, time_t t, std::vector<TAG> *ptags)
1722 printf(
"hs_get_tags for [%s]\n", event_name);
1743 printf(
"hs_get_tags reading tags for [%s]\n", event_name);
1747 std::vector<std::string> columns;
1753 if (columns.size() < 1) {
1754 cm_msg(
MERROR,
"hs_get_tags",
"Cannot get columns for table \'%s\', try to reconnect to the database", tname.c_str());
1769 for (
unsigned int j=0;
j<columns.size();
j+=2) {
1770 if (columns[
j] ==
"_t_time")
1772 if (columns[
j] ==
"_i_time")
1781 mstrlcpy(t.
name, columns[
j].c_str(),
sizeof(t.
name));
1795 int hs_get_last_written(time_t start_time,
int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[], time_t last_written[])
1797 for (
int i=0;
i<num_var;
i++)
1798 last_written[
i] = 0;
1803 const char* event_name,
const char* tag_name,
int var_index,
1805 time_t** time_buffer,
double**data_buffer)
1808 printf(
"hs_read_old_style: event \"%s\", tag \"%s\"\n", event_name, tag_name);
1818 for (
int j=0; s[
j];
j++) {
1820 if ((event_name[
j]==0) && (s[
j]==
'/')) {
1825 if ((event_name[
j]==0) && (s[
j]==
'_')) {
1830 if (event_name[
j]==0) {
1835 if (tolower(event_name[
j]) != tolower(s[
j])) {
1844 bool found_tag =
false;
1846 for (
unsigned v=0; v<ie->
tags.size(); v++) {
1860 printf(
"hs_read_old_style: event \"%s\", tag \"%s\", try matching event \'%s\'\n", event_name, tag_name, s);
1863 s, tag_name, var_index,
1865 time_buffer, data_buffer);
1875 int hs_read(
double start_time,
double end_time,
double interval,
1876 const char* event_name,
const char* tag_name,
int tag_index,
1878 time_t** time_buffer,
double**data_buffer)
1881 *time_buffer = NULL;
1882 *data_buffer = NULL;
1885 printf(
"hs_read: event [%s], tag [%s], index %d, start %f, end %f, dt %f, interval %f, max points %f\n",
1886 event_name, tag_name, tag_index,
1887 start_time, end_time, end_time-start_time, interval, (end_time-start_time)/interval);
1889 if (event_name==NULL)
1911 sprintf(xxx,
"%s[%d]", tag_name, tag_index);
1917 bool oldStyleEventName = (strchr(event_name,
'/')==NULL);
1919 if (oldStyleEventName)
1922 event_name, tag_name, tag_index,
1924 time_buffer, data_buffer);
1937 sprintf(cmd,
"SELECT _i_time, %s FROM %s WHERE _i_time>=%.0f and _i_time<=%.0f ORDER BY _i_time;",
1938 cname.c_str(), tname.c_str(),
1939 start_time, end_time);
1944 printf(
"hs_read: event \"%s\", tag \"%s\", index %d: Read table \"%s\" column \"%s\": status %d, nrows: %d, ncolumns: %d\n",
1945 event_name, tag_name, tag_index,
1961 if (oldStyleEventName) {
1963 event_name, tag_name, tag_index,
1965 time_buffer, data_buffer);
1981 *time_buffer = (time_t*)malloc(nrows *
sizeof(time_t));
1982 *data_buffer = (
double*)malloc(nrows *
sizeof(
double));
2004 v = atof(valuedata);
2006 if (t < start_time || t > end_time)
2012 if (tt == 0 || t >= tt + interval) {
2015 assert(row < nrows);
2017 (*time_buffer)[row] = (time_t)(att/ann);
2018 (*data_buffer)[row] = avv/ann;
2021 (*num_entries) = row;
2037 assert(row < nrows);
2039 (*time_buffer)[row] = (time_t)(att/ann);
2040 (*data_buffer)[row] = avv/ann;
2043 (*num_entries) = row;
2049 printf(
"hs_read: return %d entries\n", *num_entries);
2054 int hs_read(time_t start_time, time_t end_time, time_t interval,
2056 const char*
const event_name[],
const char*
const tag_name[],
const int tag_index[],
2058 time_t* time_buffer[],
double* data_buffer[],
2062 printf(
"hs_read: %d variables\n", num_var);
2067 for (
int i=0;
i<num_var;
i++) {
2069 if (event_name[
i]==NULL) {
2075 st[
i] =
hs_read((
double)start_time, (
double)end_time, (
double)interval,
2076 event_name[
i], tag_name[
i], tag_index[
i],
2078 &time_buffer[
i], &data_buffer[
i]);
2086 int hs_read2(time_t start_time, time_t end_time, time_t interval,
2088 const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2090 time_t* time_buffer[],
2091 double* mean_buffer[],
2092 double* rms_buffer[],
2093 double* min_buffer[],
2094 double* max_buffer[],
2097 int status =
hs_read(start_time, end_time, interval, num_var, event_name, tag_name, var_index, num_entries, time_buffer, mean_buffer, read_status);
2099 for (
int i=0;
i<num_var;
i++) {
2100 int num = num_entries[
i];
2101 rms_buffer[
i] = (
double*)malloc(
sizeof(
double)*num);
2102 min_buffer[
i] = (
double*)malloc(
sizeof(
double)*num);
2103 max_buffer[
i] = (
double*)malloc(
sizeof(
double)*num);
2105 for (
int j=0;
j<num;
j++) {
2106 rms_buffer[
i][
j] = 0;
2107 min_buffer[
i][
j] = mean_buffer[
i][
j];
2108 max_buffer[
i][
j] = mean_buffer[
i][
j];
2118 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2128 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2130 int* count_bins[],
double* mean_bins[],
double* rms_bins[],
double* min_bins[],
double* max_bins[],
2131 time_t* bins_first_time[],
double* bins_first_value[],
2132 time_t* bins_last_time[],
double* bins_last_value[],
2133 time_t
last_time[],
double last_value[],
virtual int ListColumns(const char *table, std::vector< std::string > *plist)=0
virtual bool IsConnected()=0
virtual int SetDebug(int debug)=0
virtual const char * GetColumn(int icol)=0
virtual int ListTables(std::vector< std::string > *plist)=0
virtual int Disconnect()=0
virtual int Exec(const char *sql)=0
virtual int Connect(const char *dsn=0)=0
virtual int GetNumColumns()=0
virtual int GetNumRows()=0
int Connect(const char *filename=NULL)
int Exec(const char *sql)
int ListColumns(const char *table, std::vector< std::string > *plist)
const char * GetColumn(int icol)
int ListTables(std::vector< std::string > *plist)
int hs_read_old_style(double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int var_index, int *num_entries, time_t **time_buffer, double **data_buffer)
int hs_read_binned(time_t start_time, time_t end_time, int num_bins, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], int *count_bins[], double *mean_bins[], double *rms_bins[], double *min_bins[], double *max_bins[], time_t *bins_first_time[], double *bins_first_value[], time_t *bins_last_time[], double *bins_last_value[], time_t last_time[], double last_value[], int status[])
returns HS_SUCCESS
int hs_define_event(const char *event_name, time_t timestamp, int ntags, const TAG tags[])
see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR
int hs_get_last_written(time_t start_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], time_t last_written[])
int hs_write_event(const char *event_name, time_t timestamp, int buffer_size, const char *buffer)
see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
int hs_flush_buffers()
flush buffered data to storage where it is visible to mhttpd
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
int hs_disconnect()
disconnect from history, returns HS_SUCCESS
int hs_read_buffer(time_t start_time, time_t end_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], MidasHistoryBufferInterface *buffer[], int status[])
returns HS_SUCCESS
int hs_read(time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const tag_name[], const int tag_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int st[])
see hs_read(), returns HS_SUCCESS
int hs_connect(const char *connect_string)
returns HS_SUCCESS
int hs_get_tags(const char *event_name, time_t t, std::vector< TAG > *ptags)
get list of history variables for given event (use event names returned by hs_get_events()) that exis...
int hs_read(double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int tag_index, int *num_entries, time_t **time_buffer, double **data_buffer)
int hs_get_events(time_t t, std::vector< std::string > *pevents)
get list of events that exist(ed) at given time and later (value 0 means "return all events from begi...
int hs_set_debug(int debug)
set debug level, returns previous debug level
int hs_read2(time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *mean_buffer[], double *rms_buffer[], double *min_buffer[], double *max_buffer[], int read_status[])
std::vector< Event * > fEvents
std::string fConnectString
std::vector< std::string > fIndexEvents
#define DB_NO_MORE_SUBKEYS
#define HS_UNDEFINED_EVENT
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
BOOL equal_ustring(const char *str1, const char *str2)
static IndexEntry * FindIndexByTableName(const char *table_name)
static std::string MidasNameToSqlName(const char *s)
int WriteEvent(SqlBase *sql, Event *e, time_t t, const char *buf, int size)
static const int tid_size[]
static int sql2midasType(const char *name)
static const char * midasTypeName(int tid)
static IndexEntry * FindIndexByEventName(const char *event_name)
static const char * sql_type_mysql[]
static IndexEntryTag * FindIndexByColumnName(IndexEntry *ie, const char *column_name)
MidasHistoryInterface * MakeMidasHistoryODBC()
static IndexEntryTag * FindIndexByTagName(IndexEntry *ie, const char *tag_name)
static bool isCompatible(int tid, const char *sqlType)
static const char * tid_name[]
static void PrintTags(int ntags, const TAG tags[])
MidasHistoryInterface * MakeMidasHistorySqlDebug()
static std::vector< IndexEntry * > gHistoryIndex
static const char * midas2sqlType(int tid)
static int ReadIndex(SqlBase *sql, const char *event_name)
static const char ** sql_type
BOOL debug
debug printouts
#define message(type, str)
BOOL match(char *pat, char *str)
std::vector< TAG > tags_cache
std::vector< IndexEntryTag > tags