SAP MaxDB é um banco de dados estratégico criado para rodar em todas as soluções SAP e substituir os bancos de dados Oracle, IBM DB2 e MSSQL Server tornando as soluções SAP mais acessíveis em termos de custo para clientes de grande e médio porte. O SAP MaxDB foi construído como uma solução open source baseado em MySQL sob a licença GNU GPL, as versão anteriores do MaxDB ainda são mantidas pela comunidade open source mas a SAP não contribui mais com estas versões.
Ao longo dos últimos anos, a tecnologia SAP MaxDB continuou a evoluir com investimentos muito significativos em inovações e essas inovações não são em código aberto. Assim o mais recente produto SAP MaxDB não é open source, entretanto ele é gratuito em sua versão comunitária para uso com aplicações não SAP e possui licença comercial para uso com aplicações SAP.
Com 40 anos de inovação atuando em mais de 130 países e com mais de 100 mil clientes que utilizam soluções SAP, o SAP MaxDB ainda é um banco de dados jovem mas conta com mais de 6.500 clientes em 15.000 instalações mais soluções que utilizam liveCache e Content Server.
SAP MaxDB: http://maxdb.sap.com/
SAP MaxDB e C++ MFC
O C++ MFC utiliza as classes de fundação Microsoft e é a linguagem padrão para se desenvolver aplicativos Desktop C++ para Windows, você precisa no mínimo de uma versão profissional do Visual Studio para utilizar este framework.
A SAP disponibiliza uma API para utilizar o MaxDB com a linguagem de programação C++ utilizando os sistemas operacionais Unix, Linux e Windows, possibilitando integrar soluções Enterprise SAP que utilizam o banco de dados MaxDB com aplicações escritas em C++ ou permite que aplicações C++ utilizem o SAP MaxDB gratuitamente também em soluções que não possuem o intuito de integrar dados com os sistemas SAP.
Softwares Requeridos
Para utilizar este walkthrough completo integrando uma solução C++ com a linguagem de programação ABAP, você precisa instalar vários software entres eles o NetWeaver Application Server ABAP no qual já possui uma instalação completa do ambiente de desenvolvimento SAP com uma instancia do banco de dados MaxDB, caso queira utilizar somente o lado C++ você pode baixar o SAP MaxDB diretamente da SAP Store:
NetWeaver Application Server ABAP: Mini SAP
Download SAP MaxDB sistemas não SAP: SAP Store
SAP MaxDB SQL Studio: Desenvolvimento Aberto walkthrough
API C++ e Drivers ODBC
O Microsoft Fundation Classes permite utilizar suas classes para conectar ao MaxDB de um modo simples através do protocolo padrão ODBC, no entanto os drivers ODBC disponibilizados pela SAP não possuem a mesma arquitetura para aplicativos win32 (código nativo) x64, então precisamos utilizar o driver 32bit disponibilizado pelo SAP MaxDB SQL Studio.
Caso não queira utilizar as classes MFC, a instalação do SAP MaxDB incluída nos produtos SAP como o núcleo de desenvolvimento do sistema SAP R/3 chamado de NetWeaver Application Sever ABAP já comtempla uma API C++ para que você possa acessar o banco de dados MaxDB e se encontra no seguinte local:
C:\sapdb\clients\NSP\sdk\sqldbc\incl
C:\sapdb\NSP\db\doc\FirstSteps\SQLDBC
Conectando ao MaxDB NSP com C++
1 – Caso utilize este tutorial com o NetWeaver primeiro tenha certeza que servidor de aplicação e a instancia SAP do banco de dados está rodando, caso utilize apenas o MaxDb e C++ ignore este passo:
2 – Abra o SQL Studio utilizando o servidor MaxDB e o banco de dados NSP ou seu próprio banco de dados caso não utilize o sistema SAP:
3 – Crie uma tabela Z que significa uma tabela não SAP Standard que não será transparente no conceito do dicionário de dados do sistemas SAP para isto utilize o script logo abaixo, não se assuste para desenvolvedores não SAP isto é apenas uma tabela comum do banco de dados:
4 – Utilizaremos os drivers ODBC do SAP MaxDB SQL Studio. No painel de controle escolha ferramentas administrativas e fonte de dados ODBC de 32bit, em drivers verifique seu driver NSP:
5 – Crie uma nova fonte de dados do usuário escolha o driver NSP ou o driver apropriado e clique em concluir:
6 – Preencha os dados de conexão com o servidor e o banco de dados e finalize:
7 – No Visual Studio crie uma solução MFC Dialog Based e disponha na tela um Static Text, um List Control e um Button, utilize a figura abaixo para o design:
8 – Utilize o código abaixo para manipular dados utilizando o SAP MaxDB:
9 – Para utilizar o ABAP para ler ou gravar dados nesta mesma tabela não transparente utilizando uma Stored Procedure no MaxDB através de códigos Native SQL, utilize o link abaixo:
Programa SAP – ABAP Native SQL: MaxDB Stored Procedure parâmetros IN e OUT
Caso conecte em um banco de dados MaxDB utilizando soluções SAP tenha em mente que você deve respeitar o conceito de dados dos sistemas SAP e verificar os termos de garantia de cada produto SAP, visto que este método ao contrario do RFC ignora a camada de banco de dados SAP e o dicionário de dados ABAP.
Como você pode verificar na imagem acima no ambiente ABAP o valor flutuante não vem formatado por padrão como estão acostumados os desenvolvedores SAP que utilizam instruções Open SQL e o dicionário ABAP no entanto você pode utilizar campos criados no dicionário apenas para a manipulação do valor de saída da Stored Procedure neste caso você deve alinhar os tipos de dados entre as aplicações C++ e aplicações ABAP.
Exemplo:
Neste exemplo utilizamos a linguagem de programação C++ para conectar ao banco de dados SAP MaxDB em uma instancia do banco de dados do NetWeaver e integrar uma tabela não transparente que pode ser manipulada tanto do lado C++ como dentro do sistema SAP utilizando Native SQL.
SQL – SAP MaxDB
-- Cria tabela no schema SAPNSP CREATE TABLE SAPNSP.ZFUNCIONARIO ( ID_FUNCIONARIO INT, NOME VARCHAR (30), SOBRENOME VARCHAR(70), CARGO VARCHAR(30), SALARIO DECIMAL(9,2) ) -- Insere dados na tabela Insert into SAPNSP.ZFUNCIONARIO values (1,'Steve','Gates','Programador',2550.56) Insert into SAPNSP.ZFUNCIONARIO values (2,'Bill','Jobs','Diretor',5143.71)
CPP – arquivo h
// ConexaoSapMaxDBcppDlg.h : header file // #pragma once // Inclui classe de banco de dados MFC #include "afxdb.h" #include "afxcmn.h" // CConexaoSapMaxDBcppDlg dialog class CConexaoSapMaxDBcppDlg : public CDialogEx { public: CConexaoSapMaxDBcppDlg(CWnd* pParent = NULL); // standard constructor enum { IDD = IDD_CONEXAOSAPMAXDBCPP_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support protected: HICON m_hIcon; virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: // Cria métodos e objetos da classe CDatabase db; void conectarDB(CString dns, CString usuario, CString senha); afx_msg void OnBnClickedButton1(); CListCtrl m_tabela; };
CPP – arquivo cpp
// ConexaoSapMaxDBcppDlg.cpp : implementation file // #include "stdafx.h" #include "ConexaoSapMaxDBcpp.h" #include "ConexaoSapMaxDBcppDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CConexaoSapMaxDBcppDlg dialog CConexaoSapMaxDBcppDlg::CConexaoSapMaxDBcppDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CConexaoSapMaxDBcppDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CConexaoSapMaxDBcppDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_tabela); } BEGIN_MESSAGE_MAP(CConexaoSapMaxDBcppDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CConexaoSapMaxDBcppDlg::OnBnClickedButton1) END_MESSAGE_MAP() // CConexaoSapMaxDBcppDlg message handlers BOOL CConexaoSapMaxDBcppDlg::OnInitDialog() { CDialogEx::OnInitDialog(); SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // Inicializa dialogo // Cria o modelo de exibição de dados m_tabela.SetView(LV_VIEW_DETAILS); m_tabela.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES); return TRUE; // return TRUE unless you set the focus to a control } void CConexaoSapMaxDBcppDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } HCURSOR CConexaoSapMaxDBcppDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CConexaoSapMaxDBcppDlg::OnBnClickedButton1() { // campo de dado da tabela CString m_campo; // Abre conexão // O SAP MAXDB requer usuário e senha em caracteres UPPERCASE conectarDB(L"SAPMAXDB32", L"SAPNSP", L"PASSWORD"); // Cria um set de dados CRecordset dados(&db); // Executa instrução SQL dados.Open(CRecordset::forwardOnly, L"Select * From SAPNSP.ZFUNCIONARIO Order by 1 DESC"); // Cria item LVITEM lvItem; // cria estrutura para inserir o item typedef struct _LVITEM { UINT mask; int iItem; int iSubItem; UINT state; UINT stateMask; LPTSTR pszText; int cchTextMax; int iImage; LPARAM lParam; #if (_WIN32_IE >= 0x0300) int iIndent; #endif } LVITEM, FAR *LPLVITEM; // Define variaveis de itens int InsertItem(const LVITEM* pItem); int nItem; // Converte CString para LPTSTR atraves de um TCHAR TCHAR sz[1024]; // Verifica colunas short nFields = dados.GetODBCFieldCount(); int colunas = m_tabela.GetHeaderCtrl()->GetItemCount(); // Verifica colunas if (colunas == 0) { // Lê metadata da tabela CODBCFieldInfo field; for (UINT i = 0; i < nFields; i++) { dados.GetODBCFieldInfo(i, field); m_tabela.InsertColumn(i, field.m_strName, LVCFMT_LEFT, 100); } } // Deleta itens do controle de lista m_tabela.DeleteAllItems(); // Recupera dados da tabela while (!dados.IsEOF()) { for (short index = 0; index < nFields; index++) { dados.GetFieldValue(index, m_campo); // Retorna linha do banco de dados if (index == 0) { // Insere linha lvItem.mask = LVIF_TEXT; lvItem.iItem = 0; lvItem.iSubItem = 0; lvItem.pszText = lstrcpy(sz, m_campo); nItem = m_tabela.InsertItem(&lvItem); } // Retorna colunas da linha m_tabela.SetItemText(nItem, index, lstrcpy(sz, m_campo)); } // Move o cursor para a proxima linha dados.MoveNext(); } // Fecha o set de dados e a conexão dados.Close(); db.Close(); } void CConexaoSapMaxDBcppDlg::conectarDB(CString dns, CString usuario, CString senha) { // Cria string de conexão ODBC CString conexao; // Cria string de conexão conexao = L"DSN=" + dns + L";UID=" + usuario + L";PWD=" + senha; // Abre conexão db.OpenEx(conexao, 0); }