亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? sqldb2.cpp

?? 以O(shè)LE DB風(fēng)格訪問DB2數(shù)據(jù)庫的C++類源碼
?? CPP
?? 第 1 頁 / 共 3 頁
字號:
//////////////////////////////////////////////////////////////////////
//
// DB2 Access Object Version 1.0
//
// Developer: Jeff Lee
// Jan 10, 2003
//
//////////////////////////////////////////////////////////////////////

#include "Sqldb2.h"

#ifdef _MSC_VER
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#endif // _MSC_VER

#pragma warning(disable:4786)
#pragma warning(disable:4312)

//////////////////////////////////////////////////////////////////////
// class CSqlObject - base class to wrap DB2 CLI handles
//////////////////////////////////////////////////////////////////////

CSqlObject::CSqlObject() :
	m_nRefs(1),
	m_nHandleType(SQL_UNKNOWN_TYPE),
	m_hSql(SQL_NULL_HANDLE),
	m_pDB(NULL)
{
}

CSqlObject::~CSqlObject()
{
	Close();
}

// Closes the handle and releases resources
void CSqlObject::Close()
{
	// delete all the remained error objects:
	while (!m_listErrors.empty())
	{
		CSqlErrorInfo *pEI = m_listErrors.front();
		m_listErrors.pop_front();
		ASSERT(pEI != NULL);
		delete pEI;
	}

	// close the handle
	if (m_hSql != SQL_NULL_HANDLE)
	{
		::SQLFreeHandle(m_nHandleType, m_hSql);
		m_hSql = SQL_NULL_HANDLE;
		m_nHandleType = SQL_UNKNOWN_TYPE;
	}

	DetachDatabase();
}

// Sets a attribute of the handle
BOOL CSqlObject::SetAttribute(SQLINTEGER nAttr, SQLPOINTER pValue, SQLINTEGER nValueSize)
{
	ASSERT(IsOpen());
	SQLRETURN nSqlRet;
	switch (m_nHandleType)
	{
	case SQL_HANDLE_DBC:
		nSqlRet = ::SQLSetConnectAttr(m_hSql, nAttr, pValue, nValueSize);
		break;

	case SQL_HANDLE_STMT:
		nSqlRet = ::SQLSetStmtAttr(m_hSql, nAttr, pValue, nValueSize);
		break;

	default:
		ASSERT(FALSE);
		break;
	}
	return SqlCheck(nSqlRet);
}

// Gets the current setting of a attribute of the handle
BOOL CSqlObject::GetAttribute(SQLINTEGER nAttr, SQLPOINTER pValue,
							  SQLINTEGER nBuffSize, SQLINTEGER* pnValueSize)
{
	ASSERT(IsOpen());
	SQLRETURN nSqlRet;
	switch (m_nHandleType)
	{
	case SQL_HANDLE_DBC:
		nSqlRet = ::SQLGetConnectAttr(m_hSql, nAttr, pValue, nBuffSize, pnValueSize);
		break;

	case SQL_HANDLE_STMT:
		nSqlRet = ::SQLGetStmtAttr(m_hSql, nAttr, pValue, nBuffSize, pnValueSize);
		break;

	default:
		ASSERT(FALSE);
		break;
	}
	return SqlCheck(nSqlRet);
}

// Decrements the reference count. Frees resources if reference count reaches 0.
int CSqlObject::Release()
{
	int nRefs = --m_nRefs;
	if (!nRefs)
		delete this;
	return nRefs;
}

// Attachs the object to a database connection
void CSqlObject::AttachDatabase(CSqlDatabase* pDB)
{
	ASSERT(pDB != NULL);
	if (this != pDB)
	{
		pDB->AddRef();
		AddRef();
		DetachDatabase();
		pDB->m_listObjects.insert(this);
	}
	m_pDB = pDB;
}

// Detachs the object from the database connection
void CSqlObject::DetachDatabase()
{
	if (m_pDB != NULL && m_pDB != this)
	{
		m_pDB->m_listObjects.erase(this);
		m_pDB->Release();
		m_pDB = NULL;
		Release();
	}
}

// Gets the last-error occured on this object
BOOL CSqlObject::GetLastError(CSqlErrorInfo& rErrorInfo)
{
	if (!m_listErrors.empty())
	{
		CSqlErrorInfo* pEI = m_listErrors.front();
		ASSERT(pEI != NULL);
		rErrorInfo = *pEI;
		m_listErrors.pop_front();
		delete pEI;
		return TRUE;
	}
	return FALSE;
}

// Checks the return code of a DB2 CLI function call
BOOL CSqlObject::SqlCheck(SQLRETURN nSqlRet)
{
	switch (nSqlRet)
	{
	case SQL_INVALID_HANDLE:
		TRACE("Invalid handle %08x\n", m_hSql);
		ASSERT(FALSE);		// it's a programmatic error
		break;

	case SQL_SUCCESS:
	case SQL_STILL_EXECUTING:
	case SQL_NEED_DATA:
	case SQL_NO_DATA_FOUND:
		return TRUE;

	case SQL_SUCCESS_WITH_INFO:
		GetErrorInfo();
		return TRUE;

	case SQL_ERROR:
	default:
		GetErrorInfo();
		break;
	}

	return FALSE;
}

// Gets diagnostic records of the previous DB2 CLI API call, and adds them to error list
void CSqlObject::GetErrorInfo()
{
	SQLSMALLINT nSize, nRec = 1;
	SQLCHAR szMsg[SQL_MAX_MESSAGE_LENGTH+1];
	SQLCHAR szState[SQL_SQLSTATE_SIZE+1];
	SQLINTEGER nCode;

	ASSERT(m_hSql != SQL_NULL_HANDLE);
	while(::SQLGetDiagRec(m_nHandleType, m_hSql, nRec, szState, &nCode,
		szMsg, SQL_MAX_MESSAGE_LENGTH+1, &nSize) == SQL_SUCCESS)
	{
		CSqlErrorInfo* pdbe = new CSqlErrorInfo;
		pdbe->m_nCode = nCode;
		pdbe->m_strDesc = (const char*)szMsg;
		::memcpy(pdbe->m_szSqlState, szState, SQL_SQLSTATE_SIZE+1);
		pdbe->m_nErrorType =
			(szState[0] == '0' && szState[1] == '1') ?
			CSqlErrorInfo::sqlInfo : CSqlErrorInfo::sqlError;

		OnSqlError(pdbe);
		nRec++;
	}
}

void CSqlObject::OnSqlError(CSqlErrorInfo* pErrorInfo)
{
	m_listErrors.push_back(pErrorInfo);
}

//////////////////////////////////////////////////////////////////////
// class CSqlDatabase - Represents a connection to a database
//////////////////////////////////////////////////////////////////////

SQLHANDLE CSqlDatabase::m_henv = SQL_NULL_HANDLE;

CSqlDatabase::CSqlDatabase() :
	m_dwOption(0)
{
}

CSqlDatabase::~CSqlDatabase()
{
	Close();
}

// Global initialization - allocates and initializes the DB2 environment handle
BOOL CSqlDatabase::Initialize(BOOL bMultiThread)
{
	if (SQL_NULL_HANDLE == m_henv)
	{
		if (!bMultiThread)
			SetEnvAttr(SQL_ATTR_PROCESSCTL,
			SQL_PROCESSCTL_NOTHREAD | SQL_PROCESSCTL_NOFORK);

		SQLRETURN nSqlRet = ::SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv);
		if (nSqlRet != SQL_SUCCESS)
		{
			TRACE0("Fail to allocate DB2 CLI environment handle");
			return FALSE;
		}
	}
	return TRUE;
}

// Global cleanup - closes the environment handle and frees any resources
void CSqlDatabase::Uninitialize()
{
	if (m_henv != SQL_NULL_HANDLE)
	{
		::SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
		m_henv = SQL_NULL_HANDLE;
	}
}

// Sets the attribute of DB2 CLI environment
BOOL CSqlDatabase::SetEnvAttr(SQLINTEGER nAttr, SQLINTEGER nValue)
{
	SQLRETURN nSqlRet = ::SQLSetEnvAttr(m_henv, nAttr, (SQLPOINTER) nValue, 0);
	return nSqlRet == SQL_SUCCESS;
}

// Gets the attribute of DB2 CLI environment
BOOL CSqlDatabase::GetEnvAttr(SQLINTEGER nAttr, SQLINTEGER& nValue)
{
	SQLRETURN nSqlRet = ::SQLGetEnvAttr(m_henv, nAttr, (SQLPOINTER) &nValue, 0, NULL);
	return nSqlRet == SQL_SUCCESS;
}

// Establishes a connection to a database
// Arguments:
//	dwOption - Specifies the attribute of the database connection. It can be 0 or
//		a combination of the following values:
//		readOnly:
//			Specifies the connection is read-only. By default it is read-write
//		manualCommit:
//			The application must manually, explicitly commit or rollback transactions
//			with CommitTrans() or RollbackTrans() calls. By default DB2 implicitly
//			commits each statement automatically.
//		autoUnlock:
//			Specifies the read locks are released when the cursor is closed.
//			By default the read locks are not released automatically.
//	dwTxnIsolation - Sets the transaction isolation level. See DB2 documentation
//		about Transaction Isolation Level.
BOOL CSqlDatabase::Connect(PCSTR pszDB, PCSTR pszUser, PCSTR pszPwd,
						   DWORD dwOption, DWORD dwTxnIsolation)
{
	// close the existing connection
	Close();
	AttachDatabase(this);

	// allocate environment handle
	//if (!Initialize())
	//	return FALSE;

	// allocate a connection handle
	m_nHandleType = SQL_HANDLE_DBC;
	ASSERT(m_henv != SQL_NULL_HANDLE);
	SQLRETURN nSqlRet = ::SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hSql);
	if (!SqlCheck(nSqlRet))
		return FALSE;

	// connect to the database
	nSqlRet = ::SQLConnect(m_hSql,
		(SQLCHAR*)pszDB, SQL_NTS,
		(SQLCHAR*)pszUser, SQL_NTS,
		(SQLCHAR*)pszPwd, SQL_NTS);
	if (!SqlCheck(nSqlRet))
		return FALSE;

	// set connection attributes:
	m_dwOption = dwOption;
	if (dwOption & readOnly)
		SetAttribute(SQL_ATTR_ACCESS_MODE, (SQLPOINTER)SQL_MODE_READ_ONLY);
	if (dwOption & manualCommit)
		SetAttribute(SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF);
	if (dwOption & autoUnlock)
		SetAttribute(SQL_ATTR_CLOSE_BEHAVIOR, (SQLPOINTER)SQL_CC_RELEASE);
	if (!SetAttribute(SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)dwTxnIsolation))
		return FALSE;

	return TRUE;
}

// Closes a database connection
void CSqlDatabase::Close()
{
	// close all open statement objects
	while (!m_listObjects.empty())
	{
		CSqlObject* pSqlObj = *m_listObjects.begin();
		ASSERT(pSqlObj != NULL);
		pSqlObj->Close();
	}

	if (m_hSql != SQL_NULL_HANDLE)
		::SQLDisconnect(m_hSql);
	CSqlObject::Close();
}

// Begins a new transaction
BOOL CSqlDatabase::BeginTrans()
{
	if (!(m_dwOption & manualCommit))
		return SqlCheck(SetAttribute(SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF));
	return TRUE;
}

// Saves any changes and ends the current transaction
BOOL CSqlDatabase::CommitTrans()
{
	BOOL bOK = SqlCheck(::SQLTransact(m_henv, m_hSql, SQL_COMMIT));
	if (!(m_dwOption & manualCommit))
		SetAttribute(SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON);
	return bOK;
}

// Cancels any changes made during the current transaction and ends the transaction
BOOL CSqlDatabase::RollbackTrans()
{
	BOOL bOK = SqlCheck(::SQLTransact(m_henv, m_hSql, SQL_ROLLBACK));
	if (!(m_dwOption & manualCommit))
		SetAttribute(SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON);
	return bOK;
}

//////////////////////////////////////////////////////////////////////
// class CSqlCommand - Defines a specific command (SQL statement)
//////////////////////////////////////////////////////////////////////

CSqlCommand::CSqlCommand() :
	m_dwOption(0),
	m_listParams(16)
{
}

CSqlCommand::~CSqlCommand()
{
	Close();
}

// Creates and initializes a CSqlCommand object
// Arguments:
//	pDB - The pointer to the database connection that the command runs upon.
//	dwOption - Specifies the command option. It can be 0 or a combination of
//		the following values:
//		execDirect:
//			Executes command directly without preparation. By default the SQL
//			statement is sent to DBMS to be prepared (equivalent to compile).
//			Use this option if the command is to be executed only once.
//		autoCloseCursor:
//			Automatically closes an open cursor if a second cursor is opened.
//			By default, DB2 CLI doesn't chain the close and open statements.
//		nonScanEscape:
//			Disables the scan of SQL string for escape clauses. This will
//			eliminate some of the scan overhead.
//			See DB2 documentation about Vendor Escape Clauses.
//		preFetch:
//			Tells the server to prefetch the next block of data immediately
//			after sending the current block.
BOOL CSqlCommand::Create(CSqlDatabase* pDB, DWORD dwOption)
{
	// attach to database connect
	ASSERT(pDB != NULL);
	ASSERT(pDB->IsOpen());
	Close();
	AttachDatabase(pDB);

	// allocate stmt handle
	m_nHandleType = SQL_HANDLE_STMT;
	SQLRETURN nSqlRet = ::SQLAllocHandle(SQL_HANDLE_STMT, m_pDB->GetHandle(), &m_hSql);
	if (!m_pDB->SqlCheck(nSqlRet))
		return FALSE;

	// set command option
	m_dwOption = dwOption;
	if (m_dwOption & autoCloseCursor)
		SetAttribute(SQL_ATTR_CLOSEOPEN, (SQLPOINTER)1);
	if (m_dwOption & nonScanEscape)
		SetAttribute(SQL_ATTR_NOSCAN, (SQLPOINTER) SQL_NOSCAN_ON);
	if (m_dwOption & preFetch)
		SetAttribute(SQL_ATTR_PREFETCH, (SQLPOINTER) SQL_PREFETCH_ON);

	SetAttribute(SQL_ATTR_DEFERRED_PREPARE, (SQLPOINTER)SQL_DEFERRED_PREPARE_ON);
	SetAttribute(SQL_ATTR_CURSOR_HOLD, (SQLPOINTER) SQL_CURSOR_HOLD_ON);
	return TRUE;
}

// Closes the command object
void CSqlCommand::Close()
{
	//if (m_hSql != SQL_NULL_HANDLE)
	//{
	//	::SQLFreeStmt(GetHandle(), SQL_UNBIND);
	//	::SQLFreeStmt(GetHandle(), SQL_RESET_PARAMS);
	//	::SQLFreeStmt(GetHandle(), SQL_CLOSE);
	//}
	m_listParams.RemoveAll();
	CSqlObject::Close();
}

// Unbinds parameters and resets the command handle for reuse
void CSqlCommand::Reset()
{
	if (IsOpen())
	{
		// close any open cursors
		if (!(m_dwOption & autoCloseCursor))
			::SQLFreeStmt(GetHandle(), SQL_CLOSE);
		// unbind parameters
		SqlCheck(::SQLFreeStmt(GetHandle(), SQL_RESET_PARAMS));
	}

	m_strSQL.erase();
	m_listParams.RemoveAll();
}

// Specifies SQL statement to be executed, and prepare the statetment
// if execDirect option not specified
BOOL CSqlCommand::SetCommand(PCSTR lpszSQL)
{
	if (!BindParameters())
		return FALSE;

	if (m_strSQL != lpszSQL)
		m_strSQL = lpszSQL;
	return (m_dwOption & execDirect) ? TRUE :
		SqlCheck(::SQLPrepare(m_hSql, (SQLCHAR*)lpszSQL, SQL_NTS));
}

// Executes the SQL statement
BOOL CSqlCommand::Execute()
{
	ASSERT(IsOpen());
	TRACE("Execute SQL statement:\n%s\n", m_strSQL.data());
	return SqlCheck((m_dwOption & execDirect) ?
		::SQLExecDirect(m_hSql, (SQLCHAR*)m_strSQL.data(), SQL_NTS) :
		::SQLExecute(m_hSql));
}

// Returns the count of rows that were affected by the SQL statement
// SELECT, UPDATE, INSERT, or DELETE
SQLINTEGER CSqlCommand::GetRowCount()
{
	SQLINTEGER nRowCount;
	if (!SqlCheck(::SQLRowCount(m_hSql, &nRowCount)))
		nRowCount = -1;
	else if (nRowCount < 0)
		nRowCount = 0;
	return nRowCount;
}

// Binds all parameters in the parameter list to the statement handle
BOOL CSqlCommand::BindParameters()
{
	ASSERT(IsOpen());
	for (int n=0; n<(int)m_listParams.GetSize(); n++)
		if (!m_listParams[n].Bind(this, n+1))
			return FALSE;
	return TRUE;
}

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
精品一二三四区| 一区二区三区国产| 韩国一区二区视频| 国产亚洲1区2区3区| 久草热8精品视频在线观看| 精品福利av导航| 国产成人精品亚洲日本在线桃色| 国产亚洲1区2区3区| 成人av免费观看| 夜夜爽夜夜爽精品视频| 欧美一卡二卡三卡| 国产精品一品视频| 亚洲天堂免费看| 欧美一区二视频| 成人晚上爱看视频| 一区二区欧美精品| 日韩免费看的电影| 成人h动漫精品一区二区| 一区二区三区在线免费播放| 欧美丝袜第三区| 韩国中文字幕2020精品| 亚洲欧美另类久久久精品| 欧美日韩大陆一区二区| 国产精品一级二级三级| 亚洲综合男人的天堂| 精品区一区二区| 91蜜桃免费观看视频| 爽好久久久欧美精品| 亚洲国产精品99久久久久久久久| 欧美三级蜜桃2在线观看| 国产精品99久久久久久久vr| 一区二区三区毛片| 久久精品人人做人人综合| 91福利在线播放| 国产精品一区二区视频| 午夜精品福利一区二区三区蜜桃| 久久亚洲综合色| 欧美视频在线一区二区三区| 成人激情校园春色| 毛片基地黄久久久久久天堂| 一区二区三区在线视频播放| 久久精品亚洲精品国产欧美kt∨| 欧美亚洲免费在线一区| 国产·精品毛片| 卡一卡二国产精品| 亚洲一区二区黄色| 国产精品麻豆99久久久久久| 日韩一区二区免费电影| 欧美视频一区二区三区四区| a亚洲天堂av| 国产成人综合精品三级| 日本va欧美va欧美va精品| 亚洲制服丝袜av| 国产精品不卡视频| 国产女同性恋一区二区| 日韩欧美一级特黄在线播放| 欧美色成人综合| 91在线视频在线| 国产福利一区二区三区在线视频| 美女看a上一区| 首页国产丝袜综合| 亚洲午夜影视影院在线观看| 亚洲精品一二三| 国产精品超碰97尤物18| 国产精品伦理一区二区| 久久久久久久精| 久久天堂av综合合色蜜桃网| 日韩欧美久久一区| 日韩一区二区免费在线电影| 91精品蜜臀在线一区尤物| 欧美亚洲高清一区二区三区不卡| 91麻豆免费观看| 色婷婷av一区二区三区软件 | 国产成人综合网站| 狠狠久久亚洲欧美| 国产综合色精品一区二区三区| 美女久久久精品| 美洲天堂一区二卡三卡四卡视频| 蜜臀av一区二区在线观看| 免费成人你懂的| 国模一区二区三区白浆| 国产精品白丝jk黑袜喷水| 国产91精品一区二区麻豆网站 | 成人黄色大片在线观看| 福利电影一区二区| 成人av小说网| 色综合天天做天天爱| 欧美日韩免费高清一区色橹橹| 欧美久久久久久蜜桃| 欧美一区二区高清| 久久久久久黄色| 亚洲欧美在线aaa| 亚洲麻豆国产自偷在线| 亚洲国产精品一区二区久久恐怖片 | 精品一区二区三区视频| 狠狠色综合播放一区二区| 国产一本一道久久香蕉| 99视频一区二区| 欧美精品一卡二卡| 精品国产成人在线影院| 国产精品萝li| 午夜视频一区在线观看| 久久se精品一区精品二区| 国产99久久久国产精品免费看| 日本大香伊一区二区三区| 欧美美女激情18p| 久久精品日韩一区二区三区| 亚洲欧美一区二区不卡| 琪琪久久久久日韩精品| 国产成人免费在线观看不卡| 欧美自拍偷拍午夜视频| 欧美mv日韩mv| 亚洲免费资源在线播放| 久久精品夜色噜噜亚洲aⅴ| 久久久久久久久久久久电影| 亚洲欧美福利一区二区| 免费视频一区二区| 成人高清视频在线观看| 欧美精品电影在线播放| 欧美国产日本视频| 日韩精品福利网| 成人一区二区三区在线观看| 欧美日韩五月天| 国产精品进线69影院| 日本aⅴ精品一区二区三区 | 国产日产欧美一区| 亚洲午夜在线视频| 成人综合激情网| 日韩视频一区二区| 洋洋成人永久网站入口| 国产成人精品亚洲777人妖| 51午夜精品国产| 一区二区在线观看不卡| 国产精品77777竹菊影视小说| 欧洲av一区二区嗯嗯嗯啊| 中文字幕va一区二区三区| 免费在线观看精品| 91福利在线看| 亚洲天堂成人在线观看| 国产乱子伦一区二区三区国色天香 | 视频在线观看91| 91原创在线视频| 国产欧美中文在线| 久久99深爱久久99精品| 欧美精品xxxxbbbb| 亚洲女与黑人做爰| 丁香婷婷深情五月亚洲| 精品国产一区二区亚洲人成毛片 | 久久精品人人做人人爽人人| 免费成人性网站| 欧美妇女性影城| 亚洲午夜免费电影| 色综合久久久久久久久久久| 日本一二三四高清不卡| 国产精品一区二区在线播放 | 777久久久精品| 亚洲国产精品久久久男人的天堂 | 日韩一区二区三区三四区视频在线观看| 一区二区三区久久久| 色呦呦网站一区| 亚洲精品视频免费观看| 91一区二区三区在线观看| 综合欧美亚洲日本| 99视频一区二区三区| 中文字幕在线不卡一区二区三区| 国产成人免费视频网站| 久久九九全国免费| 国产sm精品调教视频网站| 国产亚洲欧洲一区高清在线观看| 国产成人在线影院| 亚洲欧洲另类国产综合| 91在线视频观看| 亚洲成人中文在线| 欧美一区永久视频免费观看| 麻豆国产精品777777在线| 精品福利一二区| 国产.精品.日韩.另类.中文.在线.播放| 久久日一线二线三线suv| 国产精品18久久久| 中文字幕在线观看一区| 色综合久久久久| 日韩精品久久理论片| 久久久噜噜噜久久中文字幕色伊伊| 国产乱人伦偷精品视频不卡| 国产精品毛片无遮挡高清| 色拍拍在线精品视频8848| 一区二区三区日韩在线观看| 在线综合亚洲欧美在线视频 | 成人av动漫在线| 亚洲愉拍自拍另类高清精品| 91麻豆精品91久久久久同性| 久久精工是国产品牌吗| 国产日韩欧美电影| 色琪琪一区二区三区亚洲区| 日本亚洲电影天堂| 国产偷国产偷精品高清尤物| 91麻豆免费观看| 久久99热这里只有精品| 国产精品你懂的在线欣赏| 欧美日韩一卡二卡三卡|