RFC через ODBC используя C++

Автор Sed0Y, Травень 19, 2011, 06:26:30 ПП

Попередня тема - Наступна тема

0 Користувачі і 2 Гостей дивляться цю тему.

Sed0Y

Не знаю точно в какой раздет размещать, поместил сюда - так что сильно не пинайте.


Есть такие кто передает - дергает данные через ODBC?
меня волнует такой вопрос

как с С++ вернуть в САП таблицу с данными которые получаю запросом к базе???
Получить данные могу

...
RETCODE retcode;// Return code
SQLCHAR     one[10],
                   two[10];
...
SQLCHAR *sqlStr = (SQLCHAR *)"{SELECT one two FROM tabl where 1<>2}";
....
        retcode = SQLExecDirect(hSqlStmt, sqlStr, SQL_NTS);
        if (retcode != SQL_SUCCESS )
{
printf("Error SQL Execute Direct\n");
}

        retcode = SQLBindCol(hSqlStmt, 1, SQL_CHAR, (SQLPOINTER) one, sizeof(one), &rlength);
        if (retcode != SQL_SUCCESS )
{
printf("Error binding one\n");
}
        retcode = SQLBindCol(hSqlStmt, 2, SQL_CHAR, (SQLPOINTER) two, sizeof(two), &rlength);
        if (retcode != SQL_SUCCESS )
{
printf("Error binding two\n");
}

i = 0;
while ((retcode = SQLFetch(hSqlStmt)) == SQL_SUCCESS)
{
printf("\n %s %s", one, two); // тут вывожу свои параметры
}


Одно заначение вернуть не проблема к примеру:

memsetR (&parameters[0], 0, sizeofR(parameters));
parameters[0].name = cU("MESSAGE");
parameters[0].nlen = strlenU ((rfc_char_t*) parameters[0].name);
parameters[0].addr = &mess;
parameters[0].leng = 0;
parameters[0].type = RFCTYPE_STRING;


parameters[1].name = NULL;

tables[0].name = NULL; /* no tables */

rfc_rc = RfcSendData (rfc_handle,
  parameters,
  tables
);
return rfc_rc;
}


А вот как их всунуть в таблицу и вернуть, не заню...

№1

Цитата: Sed0Y від Травень 19, 2011, 06:26:30 ПП
как с С++ вернуть в САП таблицу с данными которые получаю запросом к базе???
Очень сильно не советую кидать данные в базу минуя сервер приложений SAP. Вас базисники просто убьют!!!
Мой блог

NachDenken

лучше использовать BAPI, они как раз для этого придуманы.

NachDenken

Цитата: №1 від Травень 20, 2011, 11:11:08 ДП
Очень сильно не советую кидать данные в базу минуя сервер приложений SAP. Вас базисники просто убьют!!!
остается вопрос как базисники ему дали права на оракловскую базу :)

Dmitriy

#4
Цитата: NachDenken від Травень 20, 2011, 01:58:35 ПП
остается вопрос как базисники ему дали права на оракловскую базу :)
Православные базисники исчо не то иногда учудяють-с! :D

Sed0Y

Спасибо всем за внимание. я разобрался как это сделать. Если кому-то будет нужно, напишите я расскажу, т.к. много писать.

А по поводу "Очень сильно не советую кидать данные в базу минуя сервер приложений SAP. Вас базисники просто убьют!!!"
я может не полностью описал потребность этого...

коротко - Я с САПа передаю кое какие данные (другой фирме, к другой БД..., где нет доступа к САП а может и есть, но если так сделано значит нужно...), там они обрабатываются и таблицой мне возвращают эти обработанные данные, потом я эти данные обрабатываю (уже на стороне САПа) и заношу в "Z" таблицы(поля) в САПе...

Uukrul

Цитата: Sed0Y від Травень 23, 2011, 05:15:01 ПП
коротко - Я с САПа передаю кое какие данные (другой фирме, к другой БД..., где нет доступа к САП а может и есть, но если так сделано значит нужно...), там они обрабатываются и таблицой мне возвращают эти обработанные данные, потом я эти данные обрабатываю (уже на стороне САПа) и заношу в "Z" таблицы(поля) в САПе...
Так это что ремоутконекшен надо было просто к другой базе сделать и все? Опять же много писать... это не причина не написать.

Sed0Y

#7
я почти так и написал в теме... Только используя С++
Только для этого уже существует написан на С++ проект для работы...
Я подумал, что если кто с таким уже работал, то он бы узнал...

Цитата: Uukrul від Травень 23, 2011, 08:30:39 ПП
Опять же много писать... это не причина не написать.

Напишу конечно... Когда буду на работе...

Nexus

#8
А пользоваться SAP RFC SDK(будет поддержка балансировки и другие плюшки "официального подключения") не пробовали, единственное что нужно будет написать две RFC функции на ABAP одна которая выберет данные, другая положит.
(if you are SAP customer you can find it on http://service.sap.com/swdc under Patches for My Company's Application Components - SAP RFC SDK)

Sed0Y

как и обещал
В САП, создаем структуру таблицы которую мы будем получать заполненную в С++
у меня было всего 2 поля(целочисленных):
назовем ее ZSRFC
поля:
RFCAID   RFCINT4
RFCBID   RFCINT4


DATA:
      gv_mess(256),
      ls_frc   TYPE ZSRFC            " структура которую мы пепредаем по РФЦ в С++

  CALL FUNCTION 'GETDATA' DESTINATION 'RFC_C'
    EXPORTING
      IMPORTSTRUCT          = ls_frc " передаем туда нашу структуру
    IMPORTING
      RET                   = RESULT " тут я себе получаю результат
      MESS                  = MESS  " ну и если есть ошибка то описание ее
    TABLES
      RFCTABLE              = G_IE " собственно данные
    EXCEPTIONS
      COMMUNICATION_FAILURE = 1  MESSAGE gv_mess
      SYSTEM_FAILURE        = 2  MESSAGE gv_mess
      .


в С++ мы описываем структуру и поля покторые получим и которые будем заполнять:

static RFC_TYPEHANDLE handleOfRfcIE;

typedef struct RFCIE
{
        SAP_INT rfcaid;
#define RFCIE_RFCAID_LN      4
#define RFCIE_RFCAID_TYP     RFCTYPE_INT

        SAP_INT rfcbid;
#define RFCIE_RFCBID_LN      4
#define RFCIE_RFCBID_TYP     RFCTYPE_INT

}
RFCIE;

static RFC_UNICODE_TYPE_ELEMENT typeOfRfcIE[] =
{
{ cU("rfcaid"), RFCIE_RFCAID_TYP,    0,   4,  20,   4,  24,   4,  32 },
{ cU("rfcbid"), RFCIE_RFCBID_TYP,    0,   4,  20,   4,  24,   4,  32 }
};

#define ENTRIESIE( tab ) ( sizeofR(tab)/sizeofR((tab)[0]) )

RFCIE   imiestruct,
          exiestruct;

//.....

static RFC_RC DLL_CALL_BACK_FUNCTION GETSynDATA(RFC_HANDLE rfc_handle);
//...
rfc_char_t get_syn_dat[31] = iU("GETDATA"); // в скобках такое имя которое мы вызываем с САПа
//...


//Переходим в код ***.c где идет вызов нашей функции прописываем в инстал
static RFC_RC install(void)
{
//-------------------------------------------------------------------------------------//
/* Install Synchronization */
  fprintfU(stderr, cU("\n7.   RfcInstallFunction (%s) rfc_rc = "), get_syn_dat);

  rfc_rc = RfcInstallFunction(get_syn_dat,
                              (RFC_ONCALL) GETSynDATA,
                              NULL);
  fprintfU(stderr, cU("%d <= GET"), rfc_rc);

  if( rfc_rc != RFC_OK )
  {
    sprintfU(abort_text, cU("\nERROR: Install (%s) rfc_rc = %d"), get_syn_data, rfc_rc);
    function_abort(abort_text);
  }
//-------------------------------------------------------------------------------------//
}
static RFC_RC DLL_CALL_BACK_FUNCTION GETSynDATA(RFC_HANDLE rfc_handle)
{
//....
memsetR (&parameters[0], 0, sizeofR(parameters));

  /* Install structure 'RFC_DAT' */
rfc_rc = RfcInstallUnicodeStructure (cU("RFCIE"), /* там где typedef struct RFCIE */
   typeOfRfcIE,
   ENTRIESIE(typeOfRfcIE),
   0, NULL,
   &handleOfRfcIE );
if (rfc_rc != RFC_OK)
rfc_error (cU("RfcInstallStructure"));

  /* Importing Parameters */
parameters[0].name = cU("IMPORTSTRUCT");
parameters[0].nlen = 2;
parameters[0].addr = &imiestruct;
parameters[0].leng = RFCIE_LN;
parameters[0].type = handleOfRfcIE;
parameters[1].name = NULL;

/* Prepare internal table RFCIETABLE */
tables[0].name     = cU("RFCTABLE");
tables[0].nlen     = 8;
tables[0].type     = handleOfRfcIE;
tables[0].leng     = RFCIE_LN;
tables[0].itmode   = RFC_ITMODE_BYREFERENCE;
tables[1].name     = NULL;

    /* receive data */
    fprintfU (stderr, cU("\n<==  RfcGetData               rfc_rc = "));
    rfc_rc = RfcGetData (rfc_handle,
parameters,
tables);
   
    fprintfU (stderr, "%d", rfc_rc);

    if (rfc_rc != RFC_OK)
     rfc_error (cU("RfcGetData"));

/* Get specific info of this RFC connection*/
/* Echo structure */
exiestruct = imiestruct;

//...
retcode = SQLConnect .......
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
retcode = SQLAllocHandle (SQL_HANDLE_STMT, hDBCSQL, &hSqlStmt);

// bind---------------
//.....
while ((retcode = SQLFetch(hSqlStmt)) == SQL_SUCCESS)
{
//insert data into table--------------------
/* New structure value */
imiestruct.rfcaid = aid;
imiestruct.rfcbid = bid;
/* Append into table 'RFCIETABLE' */
lineleng = ItLeng (tables[0].ithandle);
ptr = (rfc_char_t *) ItAppLine(tables[0].ithandle);
if (ptr == NULL)
rfc_error(cU("ItAppLine"));
memcpyR ((void *)ptr, &imiestruct, lineleng);
//end insert data into table----------------
}
         }
SQLFreeConnect (hDBCSQL); // Free the allocated connection handle
SQLFreeEnv (hEnvSQL); // Free the allocated ODBC environment handle
//......
rfc_rc = RfcSendData (rfc_handle,
  parameters,
  tables
);
//....
return rfc_rc;

}


Я вставил основные важные моменты, если кому есть что добавить - пожалуйста...
Конечно я не проверял, может будет работать и без экспорта структуры с САПа и достаточно того, что он описан в С/С++ - просто уже не было времени на эксперименты...

Uukrul

Цитата: Nexus від Травень 24, 2011, 10:10:39 ДП
(if you are SAP customer you can find it on http://service.sap.com/swdc under Patches for My Company's Application Components - SAP RFC SDK)
Типа если нет доступов: NW SAP RFC SDK