예제 #1
0
string ODBCHandler::get_db_info()
{
    stringstream    info_stream;
    string	    ODBC_error; 
    SQLCHAR	    dbms_name[256], dbms_ver[256];
    SQLUINTEGER	    getdata_support;
    SQLUSMALLINT    max_concur_act;

    SQLGetInfo(dbc, SQL_DBMS_NAME, (SQLPOINTER)dbms_name,
	    sizeof(dbms_name), NULL);
    SQLGetInfo(dbc, SQL_DBMS_VER, (SQLPOINTER)dbms_ver,
	    sizeof(dbms_ver), NULL);
    SQLGetInfo(dbc, SQL_GETDATA_EXTENSIONS, (SQLPOINTER)&getdata_support,
	    0, 0);
    SQLGetInfo(dbc, SQL_MAX_CONCURRENT_ACTIVITIES, &max_concur_act, 0, 0);

    info_stream<<"DBMS Name: "<<dbms_name<<endl;
    info_stream<<"DBMS Version: "<<dbms_ver<<endl;
    if (max_concur_act == 0) {
	info_stream<<"Maximum concurrent activities: Unlimited or Undefined."<<endl;
    } else {
	info_stream<<"Maximum concurrent activities: "<<max_concur_act<<"."<<endl;
    }
    if (getdata_support & SQL_GD_ANY_ORDER)
	info_stream<<"Column read order: Any order."<<endl;
    else
	info_stream<<"Column read order: Must be retreived in order."<<endl;
    if (getdata_support & SQL_GD_ANY_COLUMN)
	info_stream<<"Column bound: Can retrieve columns before last bound one.";
    else
	info_stream<<"Column bound: Must be retrieved after last bound one.";
    return info_stream.str();
}
예제 #2
0
static PyObject* CnxnInfo_New(Connection* cnxn)
{
#ifdef _MSC_VER
#pragma warning(disable : 4365)
#endif
    CnxnInfo* p = PyObject_NEW(CnxnInfo, &CnxnInfoType);
    if (!p)
        return 0;
    Object info((PyObject*)p);

    // set defaults
    p->odbc_major             = 0;
    p->odbc_minor             = 0;
    p->supports_describeparam = false;
    p->datetime_precision     = 19; // default: "yyyy-mm-dd hh:mm:ss"
    p->need_long_data_len     = false;

    p->varchar_maxlength  = 1 * 1024 * 1024 * 1024;
    p->wvarchar_maxlength = 1 * 1024 * 1024 * 1024;
    p->binary_maxlength   = 1 * 1024 * 1024 * 1024;

    // WARNING: The GIL lock is released for the *entire* function here.  Do not
    // touch any objects, call Python APIs, etc.  We are simply making ODBC
    // calls and setting atomic values (ints & chars).  Also, make sure the lock
    // gets released -- do not add an early exit.

    SQLRETURN ret;
    Py_BEGIN_ALLOW_THREADS

    char szVer[20];
    SQLSMALLINT cch = 0;
    ret = SQLGetInfo(cnxn->hdbc, SQL_DRIVER_ODBC_VER, szVer, _countof(szVer), &cch);
    if (SQL_SUCCEEDED(ret))
    {
        char* dot = strchr(szVer, '.');
        if (dot)
        {
            *dot = '\0';
            p->odbc_major=(char)atoi(szVer);
            p->odbc_minor=(char)atoi(dot + 1);
        }
    }

    char szYN[2];
    if (SQL_SUCCEEDED(SQLGetInfo(cnxn->hdbc, SQL_DESCRIBE_PARAMETER, szYN, _countof(szYN), &cch)))
        p->supports_describeparam = szYN[0] == 'Y';

    if (SQL_SUCCEEDED(SQLGetInfo(cnxn->hdbc, SQL_NEED_LONG_DATA_LEN, szYN, _countof(szYN), &cch)))
        p->need_long_data_len = (szYN[0] == 'Y');

    GetColumnSize(cnxn, SQL_VARCHAR, &p->varchar_maxlength);
    GetColumnSize(cnxn, SQL_WVARCHAR, &p->wvarchar_maxlength);
    GetColumnSize(cnxn, SQL_VARBINARY, &p->binary_maxlength);
    GetColumnSize(cnxn, SQL_TYPE_TIMESTAMP, &p->datetime_precision);

    Py_END_ALLOW_THREADS

    return info.Detach();
}
예제 #3
0
static void
pf_odbc_get_info (PFunArgs)
{
  char *finfo = mhtml_evaluate_string (get_positional_arg (vars, 1));

  /* No errors yet! */
  gsql_clear_error_message ();

  if (database_environment_level != 0)
    {
      Database *db = get_dbref (vars);

      if ((db != (Database *)NULL) && gsql_database_connected (db))
	{
	  RETCODE status = SQL_ERROR;
	  SWORD nbytes;
	  char buf[1024];
	  int  numval;
	  ODBC_option opt;

	  strcpy (buf, "");

	  if (find_odbc_option (finfo, &opt) != 0)
	    {
	      switch (opt.type)
		{
		case ODBC_OPT_STRING:
		  status = SQLGetInfo
		    (db->hdbc, opt.code, buf, (SWORD) sizeof (buf), &nbytes);
		  break;

		case ODBC_OPT_INT32:
		  status = SQLGetInfo
		    (db->hdbc, opt.code, &numval, sizeof (numval), &nbytes); 
		  sprintf (buf, "%d", numval);
		  break;

		case ODBC_OPT_INT16:
		  status = SQLGetInfo
		    (db->hdbc, opt.code, &numval, sizeof (numval), &nbytes); 
		  sprintf (buf, "%d", numval & 0xffff);
		  break;
		}
	    }

	  if (status == SQL_SUCCESS)
	    {
	      bprintf_insert (page, start, "%s", buf);
	      *newstart += strlen (buf);
	    }
	  else
	    gsql_save_error_message (db, GSQL_DEFAULT_ERRMSG);
	}
    }
  xfree (finfo);
}
예제 #4
0
int isPostgreSQLDatabase(SQLHDBC hdbc)
{
	RETCODE		r;
	SQLCHAR string_val[1024];
	SQLSMALLINT string_len;
	
	memset(string_val, '\0', 1024);
	r = SQLGetInfo(hdbc, SQL_DBMS_NAME, string_val, sizeof(string_val), &string_len);
	
	if (r != SQL_SUCCESS) {
		printf("ni ratalo\n");
	}
	
	char seqQueryStr[1024];
	memset(seqQueryStr, '\0', 1024);
	int is_postgresql = 0;
	if (strcmp(POSTGRESQL_NAME_LONG, (const char*)string_val) == 0) {
		is_postgresql = 1;
	} else if (strcmp(POSTGRESQL_NAME_SHORT, (const char*)string_val) == 0) {
		is_postgresql = 1;
	} else if (strcmp(NETEZZA_NAME, (const char*)string_val) == 0) {
		is_postgresql = 0;
	}
	
	return is_postgresql;
}
예제 #5
0
SQLRETURN unixodbc_backend_debug::do_get_connection_info(SQLHDBC connection_handle, SQLUSMALLINT info_type, SQLPOINTER info_value_ptr, SQLSMALLINT buffer_length, SQLSMALLINT * string_length_ptr) const
{
	std::cout << " *DEBUG* get_connection_info";
	auto const return_code = SQLGetInfo(connection_handle, info_type, info_value_ptr, buffer_length, string_length_ptr);
	std::cout << " (return code " << return_code << ")" << std::endl;
	return return_code;
}
예제 #6
0
Poco::UInt32 SessionImpl::getDefaultTransactionIsolation()
{
	SQLUINTEGER isolation = 0;
	checkError(SQLGetInfo(_db, SQL_DEFAULT_TXN_ISOLATION,
		&isolation,
		0,
		0));

	return transactionIsolation(isolation);
}
예제 #7
0
SQLRETURN SQLGetInfoA( SQLHDBC connection_handle,
           SQLUSMALLINT info_type,
           SQLPOINTER info_value,
           SQLSMALLINT buffer_length,
           SQLSMALLINT *string_length )
{
    return SQLGetInfo( connection_handle,
                info_type,
                info_value,
                buffer_length,
                string_length );
}
예제 #8
0
int main(int argc, char **argv)
{
	int rc;
	HSTMT hstmt = SQL_NULL_HSTMT;
	SQLUSMALLINT info;

	test_connect();

	rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
	if (!SQL_SUCCEEDED(rc))
	{
		print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
		exit(1);
	}

	/*
	 * Print out the current SQL_CURSOR_COMMIT_BEHAVIOR and
	 * SQL_CURSOR_ROLLBACK settings. The result of this test case depends on
	 * those.
	 */
	rc = SQLGetInfo(conn, SQL_CURSOR_COMMIT_BEHAVIOR, &info, sizeof(info), NULL);
	CHECK_STMT_RESULT(rc, "SQLGetInfo failed", hstmt);
	printf("SQL_CURSOR_COMMIT_BEHAVIOR: %s\n", sql_commit_behavior_str(info));

	rc = SQLGetInfo(conn, SQL_CURSOR_ROLLBACK_BEHAVIOR, &info, sizeof(info), NULL);
	CHECK_STMT_RESULT(rc, "SQLGetInfo failed", hstmt);
	printf("SQL_CURSOR_ROLLBACK_BEHAVIOR: %s\n\n", sql_commit_behavior_str(info));

	/* Run three variations of the test */
	testLargeResult(hstmt, 0);
	testLargeResult(hstmt, 1);
	testLargeResult(hstmt, 2);

	/* Clean up */
	test_disconnect();

	return 0;
}
예제 #9
0
파일: odbc.c 프로젝트: liyvhg/gammu
/* Connects to database */
static GSM_Error SMSDODBC_Connect(GSM_SMSDConfig * Config)
{
	SQLRETURN ret;
	int field;
	char driver_name[1000];
	SQLSMALLINT len;

	for (field = 0; field < SMSD_ODBC_MAX_RETURN_STRINGS; field++) {
		Config->conn.odbc.retstr[field] = NULL;
	}

	ret = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &Config->conn.odbc.env);
	if (!SQL_SUCCEEDED(ret)) {
		SMSDODBC_LogError(Config, ret, SQL_HANDLE_ENV, Config->conn.odbc.env, "SQLAllocHandle(ENV) failed");
		return ERR_DB_DRIVER;
	}

	ret = SQLSetEnvAttr (Config->conn.odbc.env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
	if (!SQL_SUCCEEDED(ret)) {
		SMSDODBC_LogError(Config, ret, SQL_HANDLE_ENV, Config->conn.odbc.env, "SQLSetEnvAttr failed");
		return ERR_DB_CONFIG;
	}

	ret = SQLAllocHandle (SQL_HANDLE_DBC, Config->conn.odbc.env, &Config->conn.odbc.dbc);
	if (!SQL_SUCCEEDED(ret)) {
		SMSDODBC_LogError(Config, ret, SQL_HANDLE_ENV, Config->conn.odbc.env, "SQLAllocHandle(DBC) failed");
		return ERR_DB_CONFIG;
	}

	ret = SQLConnect(Config->conn.odbc.dbc,
			  (SQLCHAR*)Config->host, SQL_NTS,
			  (SQLCHAR*)Config->user, SQL_NTS,
			  (SQLCHAR*)Config->password, SQL_NTS);
	if (!SQL_SUCCEEDED(ret)) {
		SMSDODBC_LogError(Config, ret, SQL_HANDLE_DBC, Config->conn.odbc.dbc, "SQLConnect failed");
		return ERR_DB_CONNECT;
	}

	ret = SQLGetInfo(Config->conn.odbc.dbc, SQL_DRIVER_NAME, driver_name, sizeof(driver_name), &len);
	if (!SQL_SUCCEEDED(ret)) {
		SMSDODBC_LogError(Config, ret, SQL_HANDLE_DBC, Config->conn.odbc.dbc, "SQLGetInfo failed");
		return ERR_DB_CONNECT;
	} else{
		SMSD_Log(DEBUG_NOTICE, Config, "Connected to driver %s", driver_name);
	}


	return ERR_NONE;
}
예제 #10
0
void list_driver_information()
{
    SQLCHAR dbms_name[256], dbms_ver[256];
    SQLUINTEGER getdata_support;
    SQLUSMALLINT max_concur_act;
    SQLSMALLINT string_len;

    /*
     *  Find something out about the driver.
     */
    SQLGetInfo(dbc, SQL_DBMS_NAME, (SQLPOINTER)dbms_name,
	       sizeof(dbms_name), NULL);
    SQLGetInfo(dbc, SQL_DBMS_VER, (SQLPOINTER)dbms_ver,
	       sizeof(dbms_ver), NULL);
    SQLGetInfo(dbc, SQL_GETDATA_EXTENSIONS, (SQLPOINTER)&getdata_support,
	       0, 0);
    SQLGetInfo(dbc, SQL_MAX_CONCURRENT_ACTIVITIES, &max_concur_act, 0, 0);
    
    printf("Driver Information:\n");
    printf("    DBMS Name: %s\n", dbms_name);
    printf("    DBMS Version: %s\n", dbms_ver);
    if (max_concur_act == 0) {
        printf("    SQL_MAX_CONCURRENT_ACTIVITIES - no limit or undefined\n");
    } else {
        printf("    SQL_MAX_CONCURRENT_ACTIVITIES = %u\n", max_concur_act);
    }
    if (getdata_support & SQL_GD_ANY_ORDER)
        printf("    SQLGetData - columns can be retrieved in any order\n");
    else
        printf("    SQLGetData - columns must be retrieved in order\n");
    if (getdata_support & SQL_GD_ANY_COLUMN)
        printf("    SQLGetData - can retrieve columns before last bound one\n");
    else
        printf("    SQLGetData - columns must be retrieved after last bound one\n");
    printf("\n");
}
예제 #11
0
파일: common.c 프로젝트: rzsis/freetds
int
odbc_tds_version(void)
{
	static int tds_version = -1;

	ODBC_BUF *odbc_buf = NULL;
	SQLUINTEGER version;
	SQLSMALLINT len;

	if (odbc_driver_is_freetds() && tds_version < 0) {
		version = 0;
		len = 0;
		SQLGetInfo(odbc_conn, 1300 /* SQL_INFO_FREETDS_TDS_VERSION */, &version, sizeof(version), &len);
		if (len == sizeof(version))
			tds_version = (version >> 16) << 8 | (version & 0xff);
	}
예제 #12
0
int
odbc_driver_is_freetds(void)
{
    char buf[64];
    SQLSMALLINT len;
    int i;

    if (freetds_driver < 0) {
        buf[0] = 0;
        SQLGetInfo(odbc_conn, SQL_DRIVER_NAME, buf, sizeof(buf), &len);
        for (i = 0; buf[i]; ++i)
            buf[i] = tolower(buf[i]);
        freetds_driver = (strstr(buf, "tds") != NULL);
    }
    return freetds_driver;
}
예제 #13
0
int
odbc_db_is_microsoft(void)
{
    char buf[64];
    SQLSMALLINT len;
    int i;

    if (ms_db < 0) {
        buf[0] = 0;
        SQLGetInfo(odbc_conn, SQL_DBMS_NAME, buf, sizeof(buf), &len);
        for (i = 0; buf[i]; ++i)
            buf[i] = tolower(buf[i]);
        ms_db = (strstr(buf, "microsoft") != NULL);
    }
    return ms_db;
}
예제 #14
0
파일: common.c 프로젝트: angcoch/freetds
int
odbc_driver_is_freetds(void)
{
	ODBC_BUF *odbc_buf = NULL;
	SQLTCHAR buf[64];
	SQLSMALLINT len;
	int i;

	if (freetds_driver < 0) {
		buf[0] = 0;
		SQLGetInfo(odbc_conn, SQL_DRIVER_NAME, buf, sizeof(buf), &len);
		for (i = 0; buf[i]; ++i)
			buf[i] = tolower(buf[i]);
		freetds_driver = (strstr(C(buf), "tds") != NULL);
	}
	ODBC_FREE();
	return freetds_driver;
}
예제 #15
0
파일: common.c 프로젝트: angcoch/freetds
int
odbc_db_is_microsoft(void)
{
	ODBC_BUF *odbc_buf = NULL;
	SQLTCHAR buf[64];
	SQLSMALLINT len;
	int i;

	if (ms_db < 0) {
		buf[0] = 0;
		SQLGetInfo(odbc_conn, SQL_DBMS_NAME, buf, sizeof(buf), &len);
		for (i = 0; buf[i]; ++i)
			buf[i] = tolower(buf[i]);
		ms_db = (strstr(C(buf), "microsoft") != NULL);
	}
	ODBC_FREE();
	return ms_db;
}
예제 #16
0
파일: odbc_clip.c 프로젝트: amery/clip-itk
int
odbc_createconn(ClipMachine * cm)
{
	int dbl,userl,passwdl;
	char* db = _clip_parcl(cm,2,&dbl);
	char* user = _clip_parcl(cm,3,&userl);
	char* passwd = _clip_parcl(cm,4,&passwdl);
	ODBC_CONN *conn = NULL;
	SQLHDBC tmpconn;
	SQLRETURN er;
	SQLHENV henv;
	char dbms[30];

	if(!user)
		userl = 0;
	if(!passwd)
		passwdl = 0;

	if((er = SQLAllocEnv(&henv))) goto err;
	if((er = SQLAllocConnect(henv,&tmpconn))) goto err;
	if((er = SQLConnect(tmpconn,db,dbl,user,userl,passwd,passwdl))) goto err;
	/* silly PostgreSQL's ODBC driver */
	if((er = SQLGetInfo(tmpconn,SQL_DBMS_NAME,dbms,sizeof(dbms),0)))
		goto err;

	conn = calloc(sizeof(ODBC_CONN),1);
	conn->conn = tmpconn;
	conn->vtbl = &vtbl;
	conn->henv = henv;
	if(strcmp(dbms,"PostgreSQL")==0)
		conn->postgres = 1;

	return _clip_store_c_item(cm, (void *) conn, _C_ITEM_TYPE_SQL, destroy_odbc_conn);
err:
	odbc_error(cm,(conn?conn->loc:0),henv,tmpconn,0,__LINE__,er_connect);
	if(conn)
		free(conn);
	return -1;
}
예제 #17
0
파일: common.c 프로젝트: angcoch/freetds
int
odbc_tds_version(void)
{
	static int tds_version = -1;

	ODBC_BUF *odbc_buf = NULL;
	SQLTCHAR buf[64];
	SQLSMALLINT len;

	if (!odbc_driver_is_freetds())
		return 0;

	if (tds_version < 0) {
		unsigned M, m;

		buf[0] = 0;
		SQLGetInfo(odbc_conn, 1300 /* SQL_INFO_FREETDS_TDS_VERSION */, buf, sizeof(buf), &len);
		if (sscanf(C(buf), "%u.%u", &M, &m) == 2)
			tds_version = M * 0x100u + m;
	}
	ODBC_FREE();
	return tds_version < 0 ? 0: tds_version;
}
예제 #18
0
static int odbc_dispatch10(void)
{
	unsigned long retval;
	PWord rval; int rtype;
	PWord arg1; int type1;
	PWord arg2; int type2;
	PWord arg3; int type3;
	PWord arg4; int type4;
	PWord arg5; int type5;
	PWord arg6; int type6;
	PWord arg7; int type7;

	PI_getan(&arg1,&type1,1);
	if (type1 != PI_INT)
		if (!CI_get_integer((unsigned long *)&arg1,type1))
			PI_FAIL;
	PI_getan(&arg2,&type2,2);
	if (type2 != PI_INT)
		if (!CI_get_integer((unsigned long *)&arg2,type2))
			PI_FAIL;
	PI_getan(&arg3,&type3,3);
	if (type3 != PI_INT)
		if (!CI_get_integer((unsigned long *)&arg3,type3))
			PI_FAIL;
	PI_getan(&arg4,&type4,4);
	if (type4 != PI_INT)
		if (!CI_get_integer((unsigned long *)&arg4,type4))
			PI_FAIL;
	PI_getan(&arg5,&type5,5);
	if (type5 != PI_INT)
		if (!CI_get_integer((unsigned long *)&arg5,type5))
			PI_FAIL;
	PI_getan(&arg6,&type6,6);
	if (type6 != PI_INT)
		if (!CI_get_integer((unsigned long *)&arg6,type6))
			PI_FAIL;
	PI_getan(&arg7,&type7,7);


	switch(arg1)
	{
		case 0:
			retval = (unsigned long) SQLExtendedFetch(((SQLHSTMT  ) arg2),((SQLUSMALLINT  ) arg3),((SQLINTEGER  ) arg4),((SQLUINTEGER * ) arg5),((SQLUSMALLINT * ) arg6));
			break;
		case 1:
			retval = (unsigned long) SQLSetDescField(((SQLHDESC  ) arg2),((SQLSMALLINT  ) arg3),((SQLSMALLINT  ) arg4),((SQLPOINTER  ) arg5),((SQLINTEGER  ) arg6));
			break;
		case 2:
			retval = (unsigned long) SQLGetStmtAttr(((SQLHSTMT  ) arg2),((SQLINTEGER  ) arg3),((SQLPOINTER  ) arg4),((SQLINTEGER  ) arg5),((SQLINTEGER * ) arg6));
			break;
		case 3:
			retval = (unsigned long) SQLGetInfo(((SQLHDBC  ) arg2),((SQLUSMALLINT  ) arg3),((SQLPOINTER  ) arg4),((SQLSMALLINT  ) arg5),((SQLSMALLINT * ) arg6));
			break;
		case 4:
			retval = (unsigned long) SQLGetEnvAttr(((SQLHENV  ) arg2),((SQLINTEGER  ) arg3),((SQLPOINTER  ) arg4),((SQLINTEGER  ) arg5),((SQLINTEGER * ) arg6));
			break;
		case 5:
			retval = (unsigned long) SQLGetConnectAttr(((SQLHDBC  ) arg2),((SQLINTEGER  ) arg3),((SQLPOINTER  ) arg4),((SQLINTEGER  ) arg5),((SQLINTEGER * ) arg6));
			break;
		default:
			PI_FAIL;
	}
	PI_makedouble(&rval,&rtype,(double) retval);
	if (PI_unify(arg7,type7,rval,rtype))
		PI_SUCCEED;
	PI_FAIL;
}
예제 #19
0
int
ODBC_Connect (char *connStr)
{
  short buflen;
  SQLCHAR dataSource[1024];
  SQLTCHAR dsn[33];
  SQLTCHAR desc[255];
  SQLTCHAR driverInfo[255];
  SQLSMALLINT len1, len2;
  int status;
#ifdef UNICODE
  SQLWCHAR wdataSource[1024];
#endif

#if (ODBCVER < 0x0300)
  if (SQLAllocEnv (&henv) != SQL_SUCCESS)
    return -1;

  if (SQLAllocConnect (henv, &hdbc) != SQL_SUCCESS)
    return -1;
#else
  if (SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv) != SQL_SUCCESS)
    return -1;

  SQLSetEnvAttr (henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3,
      SQL_IS_UINTEGER);

  if (SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc) != SQL_SUCCESS)
    return -1;
#endif


  /*
   *  Set the application name
   */
  SQLSetConnectOption (hdbc, SQL_APPLICATION_NAME,
	(SQLULEN) TEXT ("odbctest"));


  /*
   *  Show the version number of the driver manager
   */
  status = SQLGetInfo (hdbc, SQL_DM_VER,
      driverInfo, sizeof (driverInfo), &len1);
  if (status == SQL_SUCCESS)
    {
#ifdef UNICODE
      printf ("Driver Manager: %S\n", driverInfo);
#else
      printf ("Driver Manager: %s\n", driverInfo);
#endif
    }


  /*
   *  Either use the connect string provided on the command line or
   *  ask for one. If an empty string or a ? is given, show a nice
   *  list of options
   */
  if (connStr && *connStr)
    strcpy ((char *) dataSource, connStr);
  else
    while (1)
      {
	/*
	 *  Ask for the connect string
	 */
	printf ("\nEnter ODBC connect string (? shows list): ");
	if (fgets ((char *) dataSource, sizeof (dataSource), stdin) == NULL)
	  return 1;

	/*
	 *  Remove trailing '\n'
	 */
	dataSource[strlen ((char *) dataSource) - 1] = '\0';

	/*
	 * Check if the user wants to quit
	 */
	if (!strcmp ((char *)dataSource, "quit") || !strcmp ((char *)dataSource, "exit"))
	  return -1;

	/*
	 *  If the user entered something other than a ?
	 *  break out of the while loop
	 */
	if (*dataSource && *dataSource != '?')
	  break;


	/*
	 *  Print headers
	 */
	fprintf (stderr, "\n%-32s | %-40s\n", "DSN", "Driver");
	fprintf (stderr,
	    "------------------------------------------------------------------------------\n");

	/*
	 *  Goto the first record
	 */
	if (SQLDataSources (henv, SQL_FETCH_FIRST,
		dsn, NUMTCHAR (dsn), &len1,
		desc, NUMTCHAR (desc), &len2) != SQL_SUCCESS)
	  continue;

	/*
	 *  Show all records
	 */
	do
	  {
#ifdef UNICODE
	    fprintf (stderr, "%-32S | %-40S\n", dsn, desc);
#else
	    fprintf (stderr, "%-32s | %-40s\n", dsn, desc);
#endif
	  }
	while (SQLDataSources (henv, SQL_FETCH_NEXT,
		dsn, NUMTCHAR (dsn), &len1,
		desc, NUMTCHAR (desc), &len2) == SQL_SUCCESS);
      }

#ifdef UNICODE
  strcpy_A2W (wdataSource, (char *) dataSource);
  status = SQLDriverConnectW (hdbc, 0, (SQLWCHAR *) wdataSource, SQL_NTS,
      (SQLWCHAR *) outdsn, NUMTCHAR (outdsn), &buflen, SQL_DRIVER_COMPLETE);
  if (status != SQL_SUCCESS)
    ODBC_Errors ("SQLDriverConnectW");
#else
  status = SQLDriverConnect (hdbc, 0, (SQLCHAR *) dataSource, SQL_NTS,
      (SQLCHAR *) outdsn, NUMTCHAR (outdsn), &buflen, SQL_DRIVER_COMPLETE);
  if (status != SQL_SUCCESS)
    ODBC_Errors ("SQLDriverConnect");
#endif

  if (status != SQL_SUCCESS && status != SQL_SUCCESS_WITH_INFO)
    return -1;

  connected = 1;


  /*
   *  Print out the version number and the name of the connected driver
   */
  status = SQLGetInfo (hdbc, SQL_DRIVER_VER,
      driverInfo, NUMTCHAR (driverInfo), &len1);
  if (status == SQL_SUCCESS)
    {
#ifdef UNICODE
      printf ("Driver: %S", driverInfo);
#else
      printf ("Driver: %s", driverInfo);
#endif

      status = SQLGetInfo (hdbc, SQL_DRIVER_NAME,
	  driverInfo, NUMTCHAR (driverInfo), &len1);
      if (status == SQL_SUCCESS)
	{
#ifdef UNICODE
	  printf (" (%S)", driverInfo);
#else
	  printf (" (%s)", driverInfo);
#endif
	}
      printf ("\n");
    }


  /*
   *  Show the list of supported functions in trace log
   */
#if (ODBCVER < 0x0300)
  {
     SQLUSMALLINT exists[100];

     SQLGetFunctions (hdbc, SQL_API_ALL_FUNCTIONS, exists);
  }
#else
  {
     SQLUSMALLINT exists[SQL_API_ODBC3_ALL_FUNCTIONS_SIZE];

     SQLGetFunctions (hdbc, SQL_API_ODBC3_ALL_FUNCTIONS, exists);
  }
#endif



  /*
   *  Allocate statement handle
   */
#if (ODBCVER < 0x0300)
  if (SQLAllocStmt (hdbc, &hstmt) != SQL_SUCCESS)
    return -1;
#else
  if (SQLAllocHandle (SQL_HANDLE_STMT, hdbc, &hstmt) != SQL_SUCCESS)
    return -1;
#endif

  return 0;
}
예제 #20
0
파일: data.c 프로젝트: dparnell/freetds
int
main(int argc, char *argv[])
{
	int big_endian = 1;
	char version[32];
	SQLSMALLINT version_len;

	Connect();

	if (((char *) &big_endian)[0] == 1)
		big_endian = 0;
	memset(version, 0, sizeof(version));
	SQLGetInfo(Connection, SQL_DBMS_VER, version, sizeof(version), &version_len);

	Test("NUMERIC(18,2)", "123", SQL_C_NUMERIC, "38 0 1 7B");

	/* all binary results */
	Test("CHAR(7)", "pippo", SQL_C_BINARY, "706970706F2020");
	Test("TEXT", "mickey", SQL_C_BINARY, "6D69636B6579");
	Test("VARCHAR(20)", "foo", SQL_C_BINARY, "666F6F");

	Test("BINARY(5)", "qwer", SQL_C_BINARY, "7177657200");
	Test("IMAGE", "cricetone", SQL_C_BINARY, "6372696365746F6E65");
	Test("VARBINARY(20)", "teo", SQL_C_BINARY, "74656F");
	/* TODO only MS ?? */
	if (db_is_microsoft())
		Test("TIMESTAMP", "abcdefghi", SQL_C_BINARY, "6162636465666768");

	Test("DATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, big_endian ? "0000949700FBAA2C" : "979400002CAAFB00");
	Test("SMALLDATETIME", "2004-02-24 15:16:17", SQL_C_BINARY, big_endian ? "94970394" : "97949403");

	Test("BIT", "1", SQL_C_BINARY, "01");
	Test("BIT", "0", SQL_C_BINARY, "00");
	Test("TINYINT", "231", SQL_C_BINARY, "E7");
	Test("SMALLINT", "4321", SQL_C_BINARY, big_endian ? "10E1" : "E110");
	Test("INT", "1234567", SQL_C_BINARY, big_endian ? "0012D687" : "87D61200");
	if ((db_is_microsoft() && strncmp(version, "08.00.", 6) == 0)
	    || (!db_is_microsoft() && strncmp(version, "15.00.", 6) >= 0)) {
		int old_result = result;

		Test("BIGINT", "123456789012345", SQL_C_BINARY, big_endian ? "00007048860DDF79" : "79DF0D8648700000");
		if (result && strcmp(sbuf, "13000179DF0D86487000000000000000000000") == 0) {
			fprintf(stderr, "Ignore previous error. You should configure TDS 8.0 for this!!!\n");
			if (!old_result)
				result = 0;
		}
	}

	Test("DECIMAL", "1234.5678", SQL_C_BINARY, "120001D3040000000000000000000000000000");
	Test("NUMERIC", "8765.4321", SQL_C_BINARY, "1200013D220000000000000000000000000000");

	Test("FLOAT", "1234.5678", SQL_C_BINARY, big_endian ? "40934A456D5CFAAD" : "ADFA5C6D454A9340");
	Test("REAL", "8765.4321", SQL_C_BINARY, big_endian ? "4608F5BA" : "BAF50846");

	Test("SMALLMONEY", "765.4321", SQL_C_BINARY, big_endian ? "0074CBB1" : "B1CB7400");
	Test("MONEY", "4321234.5678", SQL_C_BINARY, big_endian ? "0000000A0FA8114E" : "0A0000004E11A80F");

	/* behavior is different from MS ODBC */
	if (db_is_microsoft() && !driver_is_freetds()) {
		Test("NCHAR(7)", "donald", SQL_C_BINARY, "64006F006E0061006C0064002000");
		Test("NTEXT", "duck", SQL_C_BINARY, "6400750063006B00");
		Test("NVARCHAR(20)", "daffy", SQL_C_BINARY, "64006100660066007900");
	}

	if (db_is_microsoft())
		Test("UNIQUEIDENTIFIER", "0DDF3B64-E692-11D1-AB06-00AA00BDD685", SQL_C_BINARY,
		     big_endian ? "0DDF3B64E69211D1AB0600AA00BDD685" : "643BDF0D92E6D111AB0600AA00BDD685");

	Test("DATETIME", "2006-06-09 11:22:44", SQL_C_CHAR, "23 2006-06-09 11:22:44.000");
	Test("SMALLDATETIME", "2006-06-12 22:37:21", SQL_C_CHAR, "19 2006-06-12 22:37:00");

	Disconnect();

	if (!result)
		printf("Done successfully!\n");
	return result;
}
예제 #21
0
SQLRETURN unixodbc_backend::do_get_connection_info(SQLHDBC connection_handle, SQLUSMALLINT info_type, SQLPOINTER info_value_ptr, SQLSMALLINT buffer_length, SQLSMALLINT * string_length_ptr) const
{
	return SQLGetInfo(connection_handle, info_type, info_value_ptr, buffer_length, string_length_ptr);
}
예제 #22
0
static int
backsql_open_db_handle(
	backsql_info	*bi,
	SQLHDBC		*dbhp )
{
	/* TimesTen */
	char			DBMSName[ 32 ];
	int			rc;

	assert( dbhp != NULL );
	*dbhp = SQL_NULL_HDBC;
 
	Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_handle()\n",
		0, 0, 0 );

	rc = SQLAllocConnect( bi->sql_db_env, dbhp );
	if ( !BACKSQL_SUCCESS( rc ) ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
			"SQLAllocConnect() failed:\n",
			0, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, SQL_NULL_HDBC,
			SQL_NULL_HENV, rc );
		return LDAP_UNAVAILABLE;
	}

	rc = SQLConnect( *dbhp,
		(SQLCHAR*)bi->sql_dbname, SQL_NTS,
		(SQLCHAR*)bi->sql_dbuser, SQL_NTS,
		(SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
			"SQLConnect() to database \"%s\" %s.\n",
			bi->sql_dbname,
			rc == SQL_SUCCESS_WITH_INFO ?
				"succeeded with info" : "failed",
			0 );
		backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
		if ( rc != SQL_SUCCESS_WITH_INFO ) {
			SQLFreeConnect( *dbhp );
			return LDAP_UNAVAILABLE;
		}
	}

	/* 
	 * TimesTen : Turn off autocommit.  We must explicitly
	 * commit any transactions. 
	 */
	SQLSetConnectOption( *dbhp, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );

	/* 
	 * See if this connection is to TimesTen.  If it is,
	 * remember that fact for later use.
	 */
	/* Assume until proven otherwise */
	bi->sql_flags &= ~BSQLF_USE_REVERSE_DN;
	DBMSName[ 0 ] = '\0';
	rc = SQLGetInfo( *dbhp, SQL_DBMS_NAME, (PTR)&DBMSName,
			sizeof( DBMSName ), NULL );
	if ( rc == SQL_SUCCESS ) {
		if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
			strcmp( DBMSName, "Front-Tier" ) == 0 )
		{
			Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
				"TimesTen database!\n",
				0, 0, 0 );
			bi->sql_flags |= BSQLF_USE_REVERSE_DN;
		}

	} else {
		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
			"SQLGetInfo() failed.\n",
			0, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
		SQLDisconnect( *dbhp );
		SQLFreeConnect( *dbhp );
		return LDAP_UNAVAILABLE;
	}
	/* end TimesTen */

	Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_handle()\n",
		0, 0, 0 );

	return LDAP_SUCCESS;
}
예제 #23
0
RETCODE
backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char *query, int timeout )
{
	RETCODE		rc;

	rc = SQLAllocStmt( dbh, sth );
	if ( rc != SQL_SUCCESS ) {
		return rc;
	}

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "==>backsql_Prepare()\n", 0, 0, 0 );
#endif /* BACKSQL_TRACE */

#ifdef BACKSQL_MSSQL_WORKAROUND
	{
		char		drv_name[ 30 ];
		SWORD		len;

		SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, sizeof( drv_name ), &len );

#ifdef BACKSQL_TRACE
		Debug( LDAP_DEBUG_TRACE, "backsql_Prepare(): driver name=\"%s\"\n",
				drv_name, 0, 0 );
#endif /* BACKSQL_TRACE */

		ldap_pvt_str2upper( drv_name );
		if ( !strncmp( drv_name, "SQLSRV32.DLL", STRLENOF( "SQLSRV32.DLL" ) ) ) {
			/*
			 * stupid default result set in MS SQL Server
			 * does not support multiple active statements
			 * on the same connection -- so we are trying 
			 * to make it not to use default result set...
			 */
			Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
				"enabling MS SQL Server default result "
				"set workaround\n", 0, 0, 0 );
			rc = SQLSetStmtOption( *sth, SQL_CONCURRENCY, 
					SQL_CONCUR_ROWVER );
			if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
				Debug( LDAP_DEBUG_TRACE, "backsql_Prepare(): "
					"SQLSetStmtOption(SQL_CONCURRENCY,"
					"SQL_CONCUR_ROWVER) failed:\n", 
					0, 0, 0 );
				backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
				SQLFreeStmt( *sth, SQL_DROP );
				return rc;
			}
		}
	}
#endif /* BACKSQL_MSSQL_WORKAROUND */

	if ( timeout > 0 ) {
		Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
			"setting query timeout to %d sec.\n", 
			timeout, 0, 0 );
		rc = SQLSetStmtOption( *sth, SQL_QUERY_TIMEOUT, timeout );
		if ( rc != SQL_SUCCESS ) {
			backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
			SQLFreeStmt( *sth, SQL_DROP );
			return rc;
		}
	}

#ifdef BACKSQL_TRACE
	Debug( LDAP_DEBUG_TRACE, "<==backsql_Prepare() calling SQLPrepare()\n",
			0, 0, 0 );
#endif /* BACKSQL_TRACE */

	return SQLPrepare( *sth, (SQLCHAR *)query, SQL_NTS );
}
예제 #24
0
static int
backsql_open_db_conn( backsql_info *si, int ldap_cid, backsql_db_conn **pdbc )
{
	/* TimesTen */
	char			DBMSName[ 32 ];
	backsql_db_conn		*dbc;
	int			rc;

	assert( pdbc );
	*pdbc = NULL;
 
	Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn()\n", 0, 0, 0 );
	dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) );
	dbc->ldap_cid = ldap_cid;
	rc = SQLAllocConnect( si->db_env, &dbc->dbh );
	if ( !BACKSQL_SUCCESS( rc ) ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
			"SQLAllocConnect() failed:\n", 0, 0, 0 );
		backsql_PrintErrors( si->db_env, SQL_NULL_HDBC,
				SQL_NULL_HENV, rc );
		return LDAP_UNAVAILABLE;
	}

	rc = SQLConnect( dbc->dbh, si->dbname, SQL_NTS, si->dbuser, 
			SQL_NTS, si->dbpasswd, SQL_NTS );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
			"SQLConnect() to database '%s' as user '%s' "
			"%s:\n", si->dbname, si->dbuser,
			rc == SQL_SUCCESS_WITH_INFO ?
			"succeeded with info" : "failed" );
		backsql_PrintErrors( si->db_env, dbc->dbh, SQL_NULL_HENV, rc );
		if ( rc != SQL_SUCCESS_WITH_INFO ) {
			return LDAP_UNAVAILABLE;
		}
	}

	/* 
	 * TimesTen : Turn off autocommit.  We must explicitly
	 * commit any transactions. 
	 */
	SQLSetConnectOption( dbc->dbh, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );

	/* 
	 * See if this connection is to TimesTen.  If it is,
	 * remember that fact for later use.
	 */
	/* Assume until proven otherwise */
	si->bsql_flags &= ~BSQLF_USE_REVERSE_DN;
	DBMSName[ 0 ] = '\0';
	rc = SQLGetInfo( dbc->dbh, SQL_DBMS_NAME, (PTR)&DBMSName,
			sizeof( DBMSName ), NULL );
	if ( rc == SQL_SUCCESS ) {
		if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
				strcmp( DBMSName, "Front-Tier" ) == 0 ) {
			Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
				"TimesTen database!\n", 0, 0, 0 );
			si->bsql_flags |= BSQLF_USE_REVERSE_DN;
		}
	} else {
		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
			"SQLGetInfo() failed:\n", 0, 0, 0 );
		backsql_PrintErrors( si->db_env, dbc->dbh, SQL_NULL_HENV, rc );
	}
	/* end TimesTen */

	Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(): "
		"connected, adding to tree\n", 0, 0, 0 );
	ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
	avl_insert( &si->db_conns, dbc, backsql_cmp_connid, NULL );
	ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
	Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn()\n", 0, 0, 0 );

	*pdbc = dbc;

	return LDAP_SUCCESS;
}
예제 #25
0
파일: MXProc.c 프로젝트: trafodion/tests
/*
---------------------------------------------------------
   TestSQLProcedures
---------------------------------------------------------
*/
PassFail TestMXSQLProcedures(TestInfo *pTestInfo)
{                  
	TEST_DECLARE;
 	char			Heading[MAX_HEADING_SIZE];
 	RETCODE			returncode;
 	SQLHANDLE 		henv;
 	SQLHANDLE 		hdbc;
 	SQLHANDLE		hstmt;
  	CHAR			*ProcStr;
	CHAR			*myTestSch = "ODBC_PROC_TEST";
 	CHAR 			createSchStr[128];
	CHAR			setSchStr[128];
	CHAR			dropSchStr[128];
 	CHAR            ProcName[NAME_LEN];
    CHAR            ServerName[NAME_LEN];
    char            SerName[4];
    SQLSMALLINT     serLen;
	SWORD			ProcType = SQL_PT_PROCEDURE;
	CHAR			opqua[NAME_LEN],opowner[NAME_LEN],opname[NAME_LEN],oremark[REM_LEN];
	SWORD			onuminpar,onumoutpar,onumresset,optype;
	SQLLEN			opqualen,opownerlen,opnamelen,onuminparlen,onumoutparlen,onumressetlen,oremarklen,optypelen;

	struct	
	{
		CHAR		*DropProc;
		CHAR		*CrtProc;
	} CreateProc[] = {
							{"DROP PROCEDURE N4210_REG",
							 "CREATE PROCEDURE N4210_REG (IN IN1 TIME) EXTERNAL NAME 'Procs.N4210' EXTERNAL PATH '/home/SQFQA/SPJRoot/odbctest_spjs' LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL NO ISOLATE"},
							{"DROP PROCEDURE N4260_REG",
							 "CREATE PROCEDURE N4260_REG (IN IN1 REAL, INOUT INOUT1 INTEGER) EXTERNAL NAME 'Procs.N4260' EXTERNAL PATH '/home/SQFQA/SPJRoot/odbctest_spjs' LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL NO ISOLATE"},
							{"DROP PROCEDURE N4261_REG",
 							 "CREATE PROCEDURE N4261_REG (IN IN1 NUMERIC, INOUT INOUT1 REAL) EXTERNAL NAME 'Procs.N4261' EXTERNAL PATH '/home/SQFQA/SPJRoot/odbctest_spjs' LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL NO ISOLATE"},
							{"DROP PROCEDURE N4264_REG",
 							 "CREATE PROCEDURE N4264_REG (IN IN1 VARCHAR(30), OUT OUT1 VARCHAR(45)) EXTERNAL NAME 'Procs.N4264' EXTERNAL PATH '/home/SQFQA/SPJRoot/odbctest_spjs' LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL NO ISOLATE"},	
							{"DROP PROCEDURE N4267_REG",
 							 "CREATE PROCEDURE N4267_REG (IN IN1 NUMERIC, INOUT INOUT1 REAL) EXTERNAL NAME 'Procs.N4267' EXTERNAL PATH '/home/SQFQA/SPJRoot/odbctest_spjs' LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL NO ISOLATE"},
							{"endloop","endloop"}
					};
	struct	
	{
		CHAR		*ProcName;
		SDWORD	NumInParams;
		SDWORD	NumOutParams;
		SDWORD	NumResSet;
		CHAR		*Remark;
	} Procedure[] = {
							{"N4210_REG",0,0,0,""},
							{"N4260_REG",0,0,0,""},
							{"N4261_REG",0,0,0,""},
							{"N4264_REG",0,0,0,""},
							{"N4267_REG",0,0,0,""},
							{"endloop",0,0,0,""}
						};
	int	i = 0, k = 0;

//===========================================================================================================
// Initialization Test Case

	LogMsg(LINEBEFORE+SHORTTIMESTAMP,"Begin testing API => MX Specific SQLProcedures | SQLProcedures | MXProc.c\n");
	
	TEST_INIT;

	TESTCASE_BEGIN("Setup for SQLProcedures tests\n");

	if(!FullConnectWithOptions(pTestInfo, CONNECT_ODBC_VERSION_3))
	{
		LogMsg(NONE,"Unable to connect\n");
		TEST_RETURN;
	}

	henv = pTestInfo->henv;
 	hdbc = pTestInfo->hdbc;
 	hstmt = (SQLHANDLE)pTestInfo->hstmt;
   	
 	returncode = SQLAllocHandle(SQL_HANDLE_STMT, (SQLHANDLE)hdbc, &hstmt);	
 	if(!CHECKRC(SQL_SUCCESS,returncode,"SQLAllocHandle"))
	{
		LogAllErrorsVer3(henv,hdbc,hstmt);
		FullDisconnect3(pTestInfo);
		TEST_RETURN;
	}

    returncode = SQLGetInfo(hdbc, SQL_SERVER_NAME, (SQLPOINTER)&ServerName, NAME_LEN, &serLen);

    strncpy(SerName, ServerName+1, 3);
    SerName[3] = '\0';

   /* sq: This test calls SQLProcedures() with wildcard characters.  It 
    * needs its own empty schema to create the procedures,  Otherwise the 
    * standard schema that everybody uses may already have other procedures 
    * created and will be returned by SQLProcedures() to confuse the test.
    */
   sprintf (createSchStr, "CREATE SCHEMA %s.%s", pTestInfo->Catalog, myTestSch);
   sprintf (setSchStr, "SET SCHEMA %s.%s", pTestInfo->Catalog, myTestSch);
   sprintf (dropSchStr, "DROP SCHEMA %s.%s cascade", pTestInfo->Catalog, myTestSch);
   returncode = SQLExecDirect(hstmt,(SQLCHAR*) dropSchStr,SQL_NTS);
   returncode = SQLExecDirect(hstmt,(SQLCHAR*) createSchStr,SQL_NTS);
   returncode = SQLExecDirect(hstmt,(SQLCHAR*) setSchStr,SQL_NTS);

	ProcStr = (char *)malloc(MAX_NOS_SIZE);

	while (_stricmp(CreateProc[i].DropProc,"endloop") != 0)
	{
        sprintf(ProcStr,"%s",CreateProc[i].DropProc);
		returncode = SQLExecDirect(hstmt,(SQLCHAR*) ProcStr,SQL_NTS); // cleanup
        sprintf(ProcStr,"%s",CreateProc[i].CrtProc);
        replace_str(ProcStr,"$$$",SerName);
		sprintf(Heading,"Procedure => %s\n",ProcStr);
		TESTCASE_BEGIN(Heading);
		
		returncode = SQLExecDirect(hstmt,(SQLCHAR*)ProcStr,SQL_NTS);
		if(returncode != SQL_SUCCESS)
		{
            TEST_FAILED;
			LogAllErrors(henv,hdbc,hstmt);
		}
		TESTCASE_END;
		i++;
	}
	
	sprintf(Heading,"Test Positive Functionality of SQLProcedures \n");
	TESTCASE_BEGIN(Heading);
	returncode = SQLProcedures(hstmt,(SQLCHAR*)pTestInfo->Catalog,(SWORD)strlen(pTestInfo->Catalog),(SQLCHAR*)myTestSch/*pTestInfo->Schema*/,(SWORD)strlen(myTestSch/*pTestInfo->Schema*/),(SQLCHAR *)"%",(SWORD)1);
	if(!CHECKRC(SQL_SUCCESS,returncode,"SQLProcedures"))
		{
			TEST_FAILED;
			LogAllErrors(henv,hdbc,hstmt);
		}
	if (returncode == SQL_SUCCESS)
		{
			strcpy(opqua,"");
			strcpy(opowner,"");
			strcpy(opname,"");
			onuminpar = 0;
			onumoutpar = 0;
			onumresset = 0;
			strcpy(oremark,"");
			optype = 0;
			SQLBindCol(hstmt,1,SQL_C_CHAR,opqua,NAME_LEN,&opqualen);
			SQLBindCol(hstmt,2,SQL_C_CHAR,opowner,NAME_LEN,&opownerlen);
			SQLBindCol(hstmt,3,SQL_C_CHAR,opname,NAME_LEN,&opnamelen);
			SQLBindCol(hstmt,4,SQL_C_SHORT,&onuminpar,0,&onuminparlen);
			SQLBindCol(hstmt,5,SQL_C_SHORT,&onumoutpar,0,&onumoutparlen);
			SQLBindCol(hstmt,6,SQL_C_SHORT,&onumresset,0,&onumressetlen);
			SQLBindCol(hstmt,7,SQL_C_CHAR,oremark,NAME_LEN,&oremarklen);
			SQLBindCol(hstmt,8,SQL_C_SHORT,&optype,0,&optypelen);
			k = 0;
			i = 0;
			while (returncode == SQL_SUCCESS)
			{
				if(strcmp(Procedure[i].ProcName,"endloop") == 0)
					break;
				returncode = SQLFetch(hstmt);
				if((returncode!=SQL_NO_DATA_FOUND) &&(!CHECKRC(SQL_SUCCESS,returncode,"SQLFetch")))
					{
						LogAllErrors(henv,hdbc,hstmt);
						TEST_FAILED;
					}
				else
					{
					if (returncode == SQL_SUCCESS)
						{
						k++;
						sprintf(Heading,"SQLProcedures: Comparing Results\n");
						TESTCASE_BEGIN(Heading);
						if ((_stricmp(pTestInfo->Catalog,opqua) == 0) 
							&& (_stricmp(myTestSch/*pTestInfo->Schema*/,opowner) == 0) 
							&& (_stricmp(Procedure[i].ProcName,opname) == 0) 
							&& (Procedure[i].NumInParams == onuminpar) 
							&& (Procedure[i].NumOutParams == onumoutpar) 
							&& (Procedure[i].NumResSet == onumresset) 
							&& (_stricmp(Procedure[i].Remark,oremark) == 0) 
							&& (ProcType == optype))
							{
								//LogMsg(NONE,"Catalog Name expect: %s and actual: %s are matched\n",pTestInfo->Catalog,opqua);
								//LogMsg(NONE,"Schema Name expect: %s and actual: %s are matched\n",pTestInfo->Schema,opowner);
								//LogMsg(NONE,"ProcName expect: %s and actual: %s are matched\n",Procedure[i].ProcName,opname);
								//LogMsg(NONE,"NumInParams expect: %d and actual: %d are matched\n",Procedure[i].NumInParams,onuminpar);
								//LogMsg(NONE,"NumOutParams expect: %d and actual: %d are matched\n",Procedure[i].NumOutParams,onumoutpar);
								//LogMsg(NONE,"NumResSet expect: %d and actual: %d are matched\n",Procedure[i].NumResSet, onumresset);
								//LogMsg(NONE,"Remark expect: %s and actual: %s are matched\n",Procedure[i].Remark,oremark);
								//LogMsg(NONE,"ProcType expect: %d and actual: %d are matched\n",ProcType,optype);
							}	
						else
							{
								TEST_FAILED;	
								if (_stricmp(pTestInfo->Catalog,opqua) != 0)
									LogMsg(ERRMSG,"Catalog Name expect: %s and actual: %s are not matched\n",pTestInfo->Catalog,opqua);
								if (_stricmp(myTestSch/*pTestInfo->Schema*/,opowner) != 0) 
									LogMsg(ERRMSG,"Schema Name expect: %s and actual: %s are not matched\n",myTestSch/*pTestInfo->Schema*/,opowner);
								if (_stricmp(Procedure[i].ProcName,opname) != 0) 
									LogMsg(ERRMSG,"ProcName expect: %s and actual: %s are not matched\n",Procedure[i].ProcName,opname);
								if (Procedure[i].NumInParams != onuminpar) 
									LogMsg(ERRMSG,"NumInParams expect: %d and actual: %d are not matched\n",Procedure[i].NumInParams,onuminpar);
								if (Procedure[i].NumOutParams != onumoutpar) 
									LogMsg(ERRMSG,"NumOutParams expect: %d and actual: %d are not matched\n",Procedure[i].NumOutParams,onumoutpar);
								if (Procedure[i].NumResSet != onumresset) 
									LogMsg(ERRMSG,"NumResSet expect: %d and actual: %d are not matched\n",Procedure[i].NumResSet, onumresset);
								if (_stricmp(Procedure[i].Remark,oremark) != 0) 
									LogMsg(ERRMSG,"Remark expect: %s and actual: %s are not matched\n",Procedure[i].Remark,oremark);
								if (ProcType != optype)
									LogMsg(ERRMSG,"ProcType expect: %d and actual: %d are not matched\n",ProcType,optype);
							}
						}
					}
					if(k == 0)
					{
						TEST_FAILED;
						LogMsg(ERRMSG,"No Data Found => Atleast one row should be fetched\n");
					}
			TESTCASE_END;
			i++;
			} // while
		}
	SQLFreeStmt(hstmt,SQL_UNBIND);
	SQLFreeStmt(hstmt,SQL_CLOSE);

	//========================================================================================================

	sprintf(Heading,"SQLProcedures: Negative test with NULL handle\n");
	TESTCASE_BEGIN(Heading);

	hstmt = (SQLHANDLE)NULL;
	strcpy(ProcName,"junkproc");

	returncode = SQLProcedures(hstmt,(SQLCHAR*)pTestInfo->Catalog,(SWORD)strlen(pTestInfo->Catalog),(SQLCHAR*)myTestSch/*pTestInfo->Schema*/,(SWORD)strlen(myTestSch/*pTestInfo->Schema*/),(SQLCHAR*)ProcName,(SWORD)strlen(ProcName));
	if(!CHECKRC(SQL_INVALID_HANDLE,returncode,"SQLProcedures"))
	{
		TEST_FAILED;
		LogAllErrors(henv,hdbc,hstmt);
	}
       returncode = SQLExecDirect(hstmt,(SQLCHAR*) dropSchStr,SQL_NTS);
	TESTCASE_END;

	//========================================================================================================

	free(ProcStr);
	FullDisconnect3(pTestInfo);
	LogMsg(SHORTTIMESTAMP+LINEAFTER,"End testing API => MX Specific SQLProcedures.\n");
	TEST_RETURN;
}
예제 #26
0
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle)
{
#ifdef SWITCH_HAVE_ODBC
	int result;
	SQLINTEGER err;
	int16_t mlen;
	unsigned char msg[200] = "", stat[10] = "";
	SQLSMALLINT valueLength = 0;
	int i = 0;

	init_odbc_handles(handle, SWITCH_FALSE); /* Init ODBC handles, if they are already initialized, don't do it again */

	if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
		switch_odbc_handle_disconnect(handle);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn);

	if (!strstr(handle->dsn, "DRIVER")) {
		result = SQLConnect(handle->con, (SQLCHAR *) handle->dsn, SQL_NTS, (SQLCHAR *) handle->username, SQL_NTS, (SQLCHAR *) handle->password, SQL_NTS);
	} else {
		SQLCHAR outstr[1024] = { 0 };
		SQLSMALLINT outstrlen = 0;
		result =
			SQLDriverConnect(handle->con, NULL, (SQLCHAR *) handle->dsn, (SQLSMALLINT) strlen(handle->dsn), outstr, sizeof(outstr), &outstrlen,
							 SQL_DRIVER_NOPROMPT);
	}

	if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
		char *err_str;
		if ((err_str = switch_odbc_handle_get_error(handle, NULL))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err_str);
			free(err_str);
		} else {
			SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, sizeof(msg), &mlen);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d [%s]\n", result, (int) err, msg);
		}

		/* Deallocate handles again, more chanses to succeed when reconnecting */
		init_odbc_handles(handle, SWITCH_TRUE); /* Reinit ODBC handles */
		return SWITCH_ODBC_FAIL;
	}

	result = SQLGetInfo(handle->con, SQL_DRIVER_NAME, (SQLCHAR *) handle->odbc_driver, 255, &valueLength);
	if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
		for (i = 0; i < valueLength; ++i)
			handle->odbc_driver[i] = (char) toupper(handle->odbc_driver[i]);
	}

	if (strstr(handle->odbc_driver, "SQORA32.DLL") != 0 || strstr(handle->odbc_driver, "SQORA64.DLL") != 0) {
		handle->is_firebird = FALSE;
		handle->is_oracle = TRUE;
	} else if (strstr(handle->odbc_driver, "FIREBIRD") != 0 || strstr(handle->odbc_driver, "FB32") != 0 || strstr(handle->odbc_driver, "FB64") != 0) {
		handle->is_firebird = TRUE;
		handle->is_oracle = FALSE;
	} else {
		handle->is_firebird = FALSE;
		handle->is_oracle = FALSE;
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn);
	handle->state = SWITCH_ODBC_STATE_CONNECTED;
	return SWITCH_ODBC_SUCCESS;
#else
	return SWITCH_ODBC_FAIL;
#endif
}
예제 #27
0
파일: switch_odbc.c 프로젝트: gujun/sscore
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle)
{
#ifdef SWITCH_HAVE_ODBC
	int result;
	SQLINTEGER err;
	int16_t mlen;
	unsigned char msg[200], stat[10];
	SQLSMALLINT valueLength = 0;
	int i = 0;

	if (handle->env == SQL_NULL_HANDLE) {
		result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);

		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n");
			return SWITCH_ODBC_FAIL;
		}

		result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);

		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n");
			SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
			return SWITCH_ODBC_FAIL;
		}

		result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);

		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result);
			SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
			return SWITCH_ODBC_FAIL;
		}
		SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
	}
	if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
		switch_odbc_handle_disconnect(handle);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn);

	if (!strstr(handle->dsn, "DRIVER")) {
		result = SQLConnect(handle->con, (SQLCHAR *) handle->dsn, SQL_NTS, (SQLCHAR *) handle->username, SQL_NTS, (SQLCHAR *) handle->password, SQL_NTS);
	} else {
		SQLCHAR outstr[1024] = { 0 };
		SQLSMALLINT outstrlen = 0;
		result =
			SQLDriverConnect(handle->con, NULL, (SQLCHAR *) handle->dsn, (SQLSMALLINT) strlen(handle->dsn), outstr, sizeof(outstr), &outstrlen,
							 SQL_DRIVER_NOPROMPT);
	}

	if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
		char *err_str;
		if ((err_str = switch_odbc_handle_get_error(handle, NULL))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err_str);
			free(err_str);
		} else {
			SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, 100, &mlen);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg);
		}
		SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
		return SWITCH_ODBC_FAIL;
	}

	result = SQLGetInfo(handle->con, SQL_DRIVER_NAME, (SQLCHAR *) handle->odbc_driver, 255, &valueLength);
	if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
		for (i = 0; i < valueLength; ++i)
			handle->odbc_driver[i] = (char) toupper(handle->odbc_driver[i]);
	}

	if (strstr(handle->odbc_driver, "FIREBIRD") != 0 || strstr(handle->odbc_driver, "FB32") != 0 || strstr(handle->odbc_driver, "FB64") != 0) {
		handle->is_firebird = TRUE;
	} else {
		handle->is_firebird = FALSE;
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn);
	handle->state = SWITCH_ODBC_STATE_CONNECTED;
	return SWITCH_ODBC_SUCCESS;
#else
	return SWITCH_ODBC_FAIL;
#endif
}
예제 #28
0
static PyObject* CnxnInfo_New(Connection* cnxn)
{
    CnxnInfo* p = PyObject_NEW(CnxnInfo, &CnxnInfoType);
    if (!p)
        return 0;
    Object info((PyObject*)p);

    // set defaults
    p->odbc_major             = 3;
    p->odbc_minor             = 50;
    p->supports_describeparam = false;
    p->datetime_precision     = 19; // default: "yyyy-mm-dd hh:mm:ss"

    // WARNING: The GIL lock is released for the *entire* function here.  Do not touch any objects, call Python APIs,
    // etc.  We are simply making ODBC calls and setting atomic values (ints & chars).  Also, make sure the lock gets
    // released -- do not add an early exit.

    SQLRETURN ret;
    Py_BEGIN_ALLOW_THREADS

    char szVer[20];
    SQLSMALLINT cch = 0;
    ret = SQLGetInfo(cnxn->hdbc, SQL_DRIVER_ODBC_VER, szVer, _countof(szVer), &cch);
    if (SQL_SUCCEEDED(ret))
    {
        char* dot = strchr(szVer, '.');
        if (dot)
        {
            *dot = '\0';
            p->odbc_major=(char)atoi(szVer);
            p->odbc_minor=(char)atoi(dot + 1);
        }
    }

    char szYN[2];
    ret = SQLGetInfo(cnxn->hdbc, SQL_DESCRIBE_PARAMETER, szYN, _countof(szYN), &cch);
    if (SQL_SUCCEEDED(ret))
    {
        p->supports_describeparam = szYN[0] == 'Y';
    }

    // What is the datetime precision?  This unfortunately requires a cursor (HSTMT).

    HSTMT hstmt = 0;
    if (SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT, cnxn->hdbc, &hstmt)))
    {
        if (SQL_SUCCEEDED(SQLGetTypeInfo(hstmt, SQL_TYPE_TIMESTAMP)) && SQL_SUCCEEDED(SQLFetch(hstmt)))
        {
            SQLINTEGER columnsize;
            if (SQL_SUCCEEDED(SQLGetData(hstmt, 3, SQL_INTEGER, &columnsize, sizeof(columnsize), 0)))
            {
                p->datetime_precision = columnsize;
            }
        }

        SQLFreeStmt(hstmt, SQL_CLOSE);
    }

    Py_END_ALLOW_THREADS

    // WARNING: Released the lock now.
    
    return info.Detach();
}
예제 #29
0
void get_info_test()
{
	printf("get_info_test\n");
	SQLHENV env;
	SQLHDBC dbc;
	
	SQLRETURN ret; /* ODBC API return status */
	SQLCHAR outstr[1024];
	SQLSMALLINT outstrlen;
	
	/* Allocate an environment handle */
	SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
	/* We want ODBC 3 support */
	SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
	/* Allocate a connection handle */
	SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
	
	ret = SQLDriverConnect(dbc, NULL, inString, SQL_NTS, outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
	if (SQL_SUCCEEDED(ret)) { printf("connected. Returned connection string was:\n\t%s\n", outstr);
		if (ret == SQL_SUCCESS_WITH_INFO) {
			printf("Driver reported the following diagnostics\n");
			extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
		}
	} else {
		printf("Failed to connect\n");
		extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
		SQLFreeHandle(SQL_HANDLE_DBC, dbc);
		SQLFreeHandle(SQL_HANDLE_ENV, env);
	}
	/*-------------------------------------------------*/
	
	SQLCHAR string_val[1024];
	SQLSMALLINT string_len;
	
	int i;
	for (i = 0; i < sizeof(driver_info) / sizeof(driver_info[0]); i++) {
		memset(string_val, '\0', 1024);
		ret = SQLGetInfo(dbc, driver_info[i].code, string_val, sizeof(string_val), &string_len);
		print_string_with_error_checking(ret, driver_info[i].code_str, string_val);
	}
	
	printf("\nSQL_DBMS_NAME test\n");
	memset(string_val, '\0', 1024);
	ret = SQLGetInfo(dbc, SQL_DBMS_NAME, string_val, sizeof(string_val), &string_len);
	print_string_with_error_checking(ret, "SQL_DBMS_NAME", string_val);
	
	char seqQueryStr[1024];
	memset(seqQueryStr, '\0', 1024);
	if (strcmp(POSTGRESQL_NAME_LONG, (const char*)string_val) == 0) {
		strcpy(seqQueryStr, "SELECT c.relname as sequence_name FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S'");
		//		seqQueryStr[0] = "SELECT c.relname as sequence_name FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S'";
	} else if (strcmp(POSTGRESQL_NAME_SHORT, (const char*)string_val) == 0) {
		strcpy(seqQueryStr, "SELECT c.relname as sequence_name FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S'");
		//		seqQueryStr[0] = "SELECT c.relname as sequence_name FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S'";
	} else if (strcmp(NETEZZA_NAME, (const char*)string_val) == 0) {
		strcpy(seqQueryStr, "SELECT SEQ_ID as sequence_name FROM _VT_SEQUENCE");
		//		seqQueryStr[0] = "SELECT SEQ_ID as sequence_name FROM _VT_SEQUENCE";
	}
	
	printf("query string: %s\n", &seqQueryStr[0]);
	
	if (strcmp(POSTGRESQL_NAME_LONG, (const char*)string_val) == 0) {
		printf("Long postgresql driver name: %s\n", string_val);
	} else if (strcmp(POSTGRESQL_NAME_SHORT, (const char*)string_val) == 0) {
		printf("Short postgresql driver name: %s\n", string_val);
	} else if (strcmp(NETEZZA_NAME, (const char*)string_val) == 0) {
		printf("Netezza driver name: %s\n", string_val);
	}
	
	/* for string values 
	 * memset(string_val, '\0', 1024);
	 * ret = SQLGetInfo(dbc, SQL_DATABASE_NAME, string_val, sizeof(string_val), &string_len);
	 * print_string_with_error_checking(ret, "SQL_DATABASE_NAME", string_val);
	 * 
	 * SQLUINTEGER u_val;
	 *	SQLUSMALLINT su_val;
	 * // for SQLUINTEGER values - mostly bitmasks , last two arguments ignored
	 * ret = SQLGetInfo(dbc, SQL_XXX, (SQLPOINTER)&u_val, 0, 0); 
	 * if (SQL_SUCCEEDED(ret)) {
	 *	printf("Returned value is %lx\n", u_val);
} else {
	// error
}

// for SQLUSMALLINT values - mostly counts/limits, last two arguments ignored
ret = SQLGetInfo(dbc, SQL_XXX, (SQLPOINTER)&su_val, 0, 0);
if (SQL_SUCCEEDED(ret)) {
	printf("Returned value is %u\n", su_val);
} else { // error 
}
*/
	/*-------------------------------------------------*/
	/* free up allocated handles */
	SQLDisconnect(dbc);
	SQLFreeHandle(SQL_HANDLE_DBC, dbc);
	SQLFreeHandle(SQL_HANDLE_ENV, env);
}
예제 #30
0
static PyObject* CnxnInfo_New(Connection* cnxn)
{
#ifdef _MSC_VER
#pragma warning(disable : 4365)
#endif
    CnxnInfo* p = PyObject_NEW(CnxnInfo, &CnxnInfoType);
    if (!p)
        return 0;
    Object info((PyObject*)p);

    // set defaults
    p->odbc_major             = 3;
    p->odbc_minor             = 50;
    p->supports_describeparam = false;
    p->datetime_precision     = 19; // default: "yyyy-mm-dd hh:mm:ss"
    p->need_long_data_len     = false;

    // WARNING: The GIL lock is released for the *entire* function here.  Do not touch any objects, call Python APIs,
    // etc.  We are simply making ODBC calls and setting atomic values (ints & chars).  Also, make sure the lock gets
    // released -- do not add an early exit.

    SQLRETURN ret;
    Py_BEGIN_ALLOW_THREADS

    char szVer[20];
    SQLSMALLINT cch = 0;
    ret = SQLGetInfo(cnxn->hdbc, SQL_DRIVER_ODBC_VER, szVer, _countof(szVer), &cch);
    if (SQL_SUCCEEDED(ret))
    {
        char* dot = strchr(szVer, '.');
        if (dot)
        {
            *dot = '\0';
            p->odbc_major=(char)atoi(szVer);
            p->odbc_minor=(char)atoi(dot + 1);
        }
    }

    char szYN[2];
    if (SQL_SUCCEEDED(SQLGetInfo(cnxn->hdbc, SQL_DESCRIBE_PARAMETER, szYN, _countof(szYN), &cch)))
        p->supports_describeparam = szYN[0] == 'Y';

    if (SQL_SUCCEEDED(SQLGetInfo(cnxn->hdbc, SQL_NEED_LONG_DATA_LEN, szYN, _countof(szYN), &cch)))
        p->need_long_data_len = (szYN[0] == 'Y');

    // These defaults are tiny, but are necessary for Access.
    p->varchar_maxlength = 255;
    p->wvarchar_maxlength = 255;
    p->binary_maxlength  = 510;

    HSTMT hstmt = 0;
    if (SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT, cnxn->hdbc, &hstmt)))
    {
        SQLINTEGER columnsize;
        if (SQL_SUCCEEDED(SQLGetTypeInfo(hstmt, SQL_TYPE_TIMESTAMP)) && SQL_SUCCEEDED(SQLFetch(hstmt)))
            if (SQL_SUCCEEDED(SQLGetData(hstmt, 3, SQL_INTEGER, &columnsize, sizeof(columnsize), 0)))
                p->datetime_precision = (int)columnsize;

        if (SQL_SUCCEEDED(SQLGetTypeInfo(hstmt, SQL_VARCHAR)) && SQL_SUCCEEDED(SQLFetch(hstmt)))
            if (SQL_SUCCEEDED(SQLGetData(hstmt, 3, SQL_INTEGER, &columnsize, sizeof(columnsize), 0)))
                p->varchar_maxlength = (int)columnsize;

        if (SQL_SUCCEEDED(SQLGetTypeInfo(hstmt, SQL_WVARCHAR)) && SQL_SUCCEEDED(SQLFetch(hstmt)))
            if (SQL_SUCCEEDED(SQLGetData(hstmt, 3, SQL_INTEGER, &columnsize, sizeof(columnsize), 0)))
                p->wvarchar_maxlength = (int)columnsize;

        if (SQL_SUCCEEDED(SQLGetTypeInfo(hstmt, SQL_BINARY)) && SQL_SUCCEEDED(SQLFetch(hstmt)))
            if (SQL_SUCCEEDED(SQLGetData(hstmt, 3, SQL_INTEGER, &columnsize, sizeof(columnsize), 0)))
                p->binary_maxlength = (int)columnsize;

        SQLFreeStmt(hstmt, SQL_CLOSE);
    }

    Py_END_ALLOW_THREADS

    // WARNING: Released the lock now.

    return info.Detach();
}