| 22 |
* |
* |
| 23 |
* $Revision$ |
* $Revision$ |
| 24 |
* $Log$ |
* $Log$ |
| 25 |
|
* Revision 1.104 2005/08/29 02:05:34 aga4096 |
| 26 |
|
* ・xnp_update_item_status(), xnp_refresh_item_status(), xnp_selective_harvesting() を追加. |
| 27 |
|
* |
| 28 |
* Revision 1.103 2005/08/23 07:34:24 tani |
* Revision 1.103 2005/08/23 07:34:24 tani |
| 29 |
* Language対応: getItems, _insetItem, updateItem |
* Language対応: getItems, _insetItem, updateItem |
| 30 |
* |
* |
| 466 |
static SQLHANDLE henv = NULL; |
static SQLHANDLE henv = NULL; |
| 467 |
static SQLHANDLE hdbc = NULL; |
static SQLHANDLE hdbc = NULL; |
| 468 |
|
|
| 469 |
|
typedef enum { |
| 470 |
|
ME_CREATED = 1, |
| 471 |
|
ME_MODIFIED, |
| 472 |
|
ME_DELETED |
| 473 |
|
} metadataevent_t; |
| 474 |
|
|
| 475 |
|
//構造体 dateがNULLなら0 |
| 476 |
|
typedef struct{ |
| 477 |
|
time_t createdTimestamp; |
| 478 |
|
time_t modifiedTimestamp; |
| 479 |
|
time_t deletedTimestamp; |
| 480 |
|
int isDeleted; |
| 481 |
|
} itemstatus_t; |
| 482 |
|
|
| 483 |
static bool processEsummary(xmlTextReaderPtr reader, pubmed_t* p); |
static bool processEsummary(xmlTextReaderPtr reader, pubmed_t* p); |
| 484 |
static bool processEsearch(xmlTextReaderPtr reader, pubmed_t* p, int* DocID ); |
static bool processEsearch(xmlTextReaderPtr reader, pubmed_t* p, int* DocID ); |
| 485 |
static void processEfetch(xmlTextReaderPtr reader, pubmed_t* p); |
static void processEfetch(xmlTextReaderPtr reader, pubmed_t* p); |
| 492 |
static result_t checkTitleConflict( sessionid_t sid, indexid_t parentIndexID, const char *title, bool *conflict ); |
static result_t checkTitleConflict( sessionid_t sid, indexid_t parentIndexID, const char *title, bool *conflict ); |
| 493 |
static result_t _insertItem( sessionid_t sid, const item_t* item, itemid_t* itemid, bool direct ); |
static result_t _insertItem( sessionid_t sid, const item_t* item, itemid_t* itemid, bool direct ); |
| 494 |
static result_t getEvents(sessionid_t sid, event_t** events, int* eventsLen, string condition ); |
static result_t getEvents(sessionid_t sid, event_t** events, int* eventsLen, string condition ); |
| 495 |
|
static result_t insertMetadataEvent( metadataevent_t me, itemid_t iid ); |
| 496 |
|
static result_t getMetadataEvent( itemid_t iid, itemstatus_t *status ); |
| 497 |
|
static result_t insertMetadataEventAuto( itemid_t iid, bool isCreate = false ); |
| 498 |
|
|
| 499 |
static void syslog_printf( char* format, ... ) |
static void syslog_printf( char* format, ... ) |
| 500 |
{ |
{ |
| 506 |
#endif |
#endif |
| 507 |
} |
} |
| 508 |
|
|
| 509 |
|
/** ',' . implode( ',', pi ) の形の文字列を作成する。先頭にcommaがあるので注意 |
| 510 |
|
* @param pi int配列 |
| 511 |
|
* @param len 配列の長さ |
| 512 |
|
*/ |
| 513 |
|
static string getCsvStr( const itemid_t *pi, int len ){ |
| 514 |
|
char *buf = new char[(sizeof(int)*3+1)*len+1]; |
| 515 |
|
buf[0] = '\0'; |
| 516 |
|
char *p = buf; |
| 517 |
|
for ( int i = 0; i < len; i++ ){ |
| 518 |
|
int len = sprintf( p, ",%u", pi[i] ); |
| 519 |
|
p += len; |
| 520 |
|
} |
| 521 |
|
string iids_str(buf); |
| 522 |
|
delete[] buf; |
| 523 |
|
return iids_str; |
| 524 |
|
} |
| 525 |
|
|
| 526 |
/** |
/** |
| 527 |
* |
* |
| 528 |
* public_item_target_userの設定値が'all'ならtrueをかえす |
* public_item_target_userの設定値が'all'ならtrueをかえす |
| 632 |
} |
} |
| 633 |
|
|
| 634 |
|
|
| 635 |
|
// SQLAllocHandle〜SQLExecDirectのエラー処理とhstmtの開放が面倒なのでクラス化する |
| 636 |
|
class sqlexec_t { |
| 637 |
|
private: |
| 638 |
|
SQLRETURN sqlcode; |
| 639 |
|
SQLHANDLE hstmt; |
| 640 |
|
public: |
| 641 |
|
SQLRETURN getSqlcode(){ return sqlcode; } |
| 642 |
|
SQLHANDLE getHstmt(){ return hstmt; } |
| 643 |
|
//SQLRETURN SQLFetch(){ return sqlcode = SQLFetch(hstmt); } // あまりwrapperを作りたくないので廃止 |
| 644 |
|
|
| 645 |
|
/** コンストラクタ: SQLAllocHandle, SQLExecDirectを行う。成功ならgetSqlcode()==SQL_SUCCESS |
| 646 |
|
* @param functionName エラーログに書く関数名 |
| 647 |
|
* @param sql 実行すべきSQL |
| 648 |
|
* @param ret エラーコードの出力先 |
| 649 |
|
*/ |
| 650 |
|
sqlexec_t( const char *functionName, string &sql, result_t *ret ){ |
| 651 |
|
sqlcode = 0; |
| 652 |
|
hstmt = 0; |
| 653 |
|
|
| 654 |
|
if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) { |
| 655 |
|
if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){ |
| 656 |
|
return; |
| 657 |
|
}else { |
| 658 |
|
string s( "SQLExecDirect in " ); |
| 659 |
|
s += functionName; |
| 660 |
|
s += " "; |
| 661 |
|
s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode ); |
| 662 |
|
s += " sql="; |
| 663 |
|
s += string( sql ); |
| 664 |
|
setLastErrorString( s.c_str( ) ); |
| 665 |
|
*ret = RES_DB_QUERY_ERROR; |
| 666 |
|
return; |
| 667 |
|
} |
| 668 |
|
}else { |
| 669 |
|
string s( "SQLAllocHandle(SQL_HANDLE_STMT,...) in " ); |
| 670 |
|
s += functionName; |
| 671 |
|
s += " "; |
| 672 |
|
s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode ); |
| 673 |
|
setLastErrorString( s.c_str( ) ); |
| 674 |
|
*ret = RES_ERROR; |
| 675 |
|
return; |
| 676 |
|
} |
| 677 |
|
} |
| 678 |
|
~sqlexec_t(){ |
| 679 |
|
if ( hstmt ) |
| 680 |
|
SQLFreeHandle( SQL_HANDLE_STMT, hstmt ); |
| 681 |
|
} |
| 682 |
|
}; |
| 683 |
|
|
| 684 |
|
|
| 685 |
/** SQLを実行する。結果は捨てる。 |
/** SQLを実行する。結果は捨てる。 |
| 4245 |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
| 4246 |
querySimple( "updateItem", sql ); |
querySimple( "updateItem", sql ); |
| 4247 |
} |
} |
| 4248 |
ret = RES_OK; |
ret = insertMetadataEventAuto( item_id, true ); |
| 4249 |
}else{ |
}else{ |
| 4250 |
string s( "SQLExecDirect in updateItem" ); |
string s( "SQLExecDirect in updateItem" ); |
| 4251 |
s += odbcDiagString( SQL_HANDLE_STMT, hstmt2, sqlcode ); |
s += odbcDiagString( SQL_HANDLE_STMT, hstmt2, sqlcode ); |
| 4440 |
ret = RES_ERROR; |
ret = RES_ERROR; |
| 4441 |
} |
} |
| 4442 |
|
|
| 4443 |
|
if ( ret == RES_OK ){ |
| 4444 |
|
ret = insertMetadataEventAuto( itemid ); |
| 4445 |
|
} |
| 4446 |
return ret; |
return ret; |
| 4447 |
} |
} |
| 4448 |
|
|
| 4870 |
+ " WHERE index_id=" + unsignedIntToString( xid ) |
+ " WHERE index_id=" + unsignedIntToString( xid ) |
| 4871 |
+ " AND item_id=" + unsignedIntToString( iid ); |
+ " AND item_id=" + unsignedIntToString( iid ); |
| 4872 |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
| 4873 |
return querySimple( "setCertifyState", sql ); |
result_t ret = querySimple( "setCertifyState", sql ); |
| 4874 |
|
if ( ret != RES_OK ) |
| 4875 |
|
return ret; |
| 4876 |
|
return insertMetadataEventAuto( iid ); |
| 4877 |
} |
} |
| 4878 |
|
|
| 4879 |
/** |
/** |
| 4961 |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
| 4962 |
ret = querySimple( "registerItem", sql ); |
ret = querySimple( "registerItem", sql ); |
| 4963 |
} |
} |
| 4964 |
|
if ( ret == RES_OK ){ |
| 4965 |
|
ret = insertMetadataEventAuto( iid ); |
| 4966 |
|
} |
| 4967 |
return ret; |
return ret; |
| 4968 |
} |
} |
| 4969 |
|
|
| 5004 |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
syslog_printf( "\nsql at %d=%s", __LINE__, sql.c_str() ); |
| 5005 |
ret = querySimple( "unregisterItem", sql ); |
ret = querySimple( "unregisterItem", sql ); |
| 5006 |
} |
} |
| 5007 |
|
if ( ret == RES_OK ){ |
| 5008 |
|
ret = insertMetadataEventAuto( iid ); |
| 5009 |
|
} |
| 5010 |
return ret; |
return ret; |
| 5011 |
} |
} |
| 5012 |
|
|
| 6200 |
} |
} |
| 6201 |
} |
} |
| 6202 |
|
|
| 6203 |
|
if ( newIndex->getOpenLevel() == index::OL_PUBLIC ){ |
| 6204 |
|
// ここでnewIndex以下の承認済みアイテムについて insertMetadataEventAuto を行う |
| 6205 |
|
string xid_str; |
| 6206 |
|
{ |
| 6207 |
|
indexid_t *descXID = 0; |
| 6208 |
|
int descXIDLen; |
| 6209 |
|
result = getDescendantIndexID( newIndex->getIndexID(), &descXID, &descXIDLen ); |
| 6210 |
|
if ( result != RES_OK ){ |
| 6211 |
|
setLastErrorString( "in updateIndex: getDescendantIndexID failed" ); |
| 6212 |
|
return RES_ERROR; |
| 6213 |
|
} |
| 6214 |
|
|
| 6215 |
|
xid_str = getCsvStr( descXID, descXIDLen ); |
| 6216 |
|
delete[] descXID; |
| 6217 |
|
} |
| 6218 |
|
|
| 6219 |
|
string sql = |
| 6220 |
|
" select distinct item_id from " + dbprefix + "_xoonips_index_item_link " |
| 6221 |
|
" where certify_state = " + unsignedIntToString(index::CERTIFIED) + |
| 6222 |
|
" and index_id in ( 0 " + xid_str + ")"; |
| 6223 |
|
sqlexec_t s( "updateIndex", sql, &result ); |
| 6224 |
|
if ( s.getSqlcode() == SQL_SUCCESS ){ |
| 6225 |
|
SQLUINTEGER iid = 0; |
| 6226 |
|
SQLLEN cbIID = 0; |
| 6227 |
|
SQLBindCol( s.getHstmt(), 1, SQL_C_ULONG, &iid , 0, &cbIID ); |
| 6228 |
|
|
| 6229 |
|
result = RES_OK; |
| 6230 |
|
while ( SQLFetch( s.getHstmt() ) == SQL_SUCCESS ){ |
| 6231 |
|
result = insertMetadataEventAuto( iid ); |
| 6232 |
|
if ( result != RES_OK ) |
| 6233 |
|
break; |
| 6234 |
|
} |
| 6235 |
|
} |
| 6236 |
|
else return result; |
| 6237 |
|
} |
| 6238 |
|
|
| 6239 |
return result; |
return result; |
| 6240 |
|
|
| 6241 |
} |
} |
| 6295 |
return result; |
return result; |
| 6296 |
} |
} |
| 6297 |
|
|
| 6298 |
/** |
result_t deleteIndexInternal( sessionid_t sid, indexid_t xid, const index_t *&index, indexid_t *&descXID, itemid_t *&affectedIIDs ) |
|
* |
|
|
* インデックスキーワードを削除する |
|
|
* |
|
|
* @param sid セッションID |
|
|
* @param xid 削除するインデックスキーワード |
|
|
* @return RES_OK 成功 |
|
|
* |
|
|
*/ |
|
|
result_t deleteIndex( sessionid_t sid, indexid_t xid ) |
|
| 6299 |
{ |
{ |
| 6300 |
char *functionName = "deleteIndex"; |
char *functionName = "deleteIndex"; |
| 6301 |
result_t result; |
result_t result; |
| 6305 |
result = sessionID2UID( sid, &uid ); // sid から uid を得る |
result = sessionID2UID( sid, &uid ); // sid から uid を得る |
| 6306 |
if( result != RES_OK ) return result; |
if( result != RES_OK ) return result; |
| 6307 |
|
|
|
const index_t *index; |
|
| 6308 |
result = getIndex( sid, xid, &index ); |
result = getIndex( sid, xid, &index ); |
| 6309 |
if ( result != RES_OK ) |
if ( result != RES_OK ) |
| 6310 |
return result; |
return result; |
| 6311 |
|
|
| 6312 |
if ( index->getIndexID() == item::IID_ROOT || index->getParentIndexID() == item::IID_ROOT ){ |
if ( index->getIndexID() == item::IID_ROOT || index->getParentIndexID() == item::IID_ROOT ){ |
|
result = RES_ERROR; |
|
| 6313 |
setLastErrorString( "in deleteIndex: cannot delete system-created-index." ); |
setLastErrorString( "in deleteIndex: cannot delete system-created-index." ); |
| 6314 |
|
return RES_ERROR; |
| 6315 |
} |
} |
| 6316 |
else { |
|
| 6317 |
if ( !isWritableInternal( sid, uid, index ) ){ |
if ( !isWritableInternal( sid, uid, index ) ){ |
| 6318 |
result = RES_NO_WRITE_ACCESS_RIGHT; |
setLastErrorString( "in deleteIndex: no write access right." ); |
| 6319 |
setLastErrorString( "in deleteIndex: no write access right." ); |
return RES_NO_WRITE_ACCESS_RIGHT; |
| 6320 |
|
} |
| 6321 |
|
|
| 6322 |
|
// 削除対象を列挙 |
| 6323 |
|
int descXIDLen; |
| 6324 |
|
result = getDescendantIndexID( xid, &descXID, &descXIDLen ); |
| 6325 |
|
if ( result != RES_OK ){ |
| 6326 |
|
setLastErrorString( "in deleteIndex: getDescendantIndexID failed" ); |
| 6327 |
|
return RES_ERROR; |
| 6328 |
|
} |
| 6329 |
|
|
| 6330 |
|
// 削除対象の中にBindersが入っている場合は、削除できない。 |
| 6331 |
|
for ( int i = 0; i < descXIDLen; i++ ){ |
| 6332 |
|
if ( descXID[i] == item::IID_BINDERS ){ |
| 6333 |
|
setLastErrorString( "in deleteIndex: target index contains Binders." ); |
| 6334 |
|
return RES_ERROR; |
| 6335 |
} |
} |
| 6336 |
else { |
} |
| 6337 |
// 削除対象を列挙 |
|
| 6338 |
indexid_t *descXID = 0; |
int affectedIIDsLen = 0; |
| 6339 |
int descXIDLen; |
if ( index->getOpenLevel() == index::OL_PUBLIC ){ |
| 6340 |
result = getDescendantIndexID( xid, &descXID, &descXIDLen ); |
// ここでnewIndex以下の承認済みアイテムを記憶しておいて あとで insertMetadataEventAuto を行う |
| 6341 |
if ( result != RES_OK ){ |
string sql = "select count(*) from " + dbprefix + "_xoonips_item_basic"; |
| 6342 |
setLastErrorString( "in deleteIndex: getDescendantIndexID failed" ); |
unsigned int iidsLen; |
| 6343 |
return RES_ERROR; |
result = queryGetUnsignedInt( "deleteIndex", sql, &iidsLen ); |
| 6344 |
} |
if ( result != RES_OK ) |
| 6345 |
|
return result; |
| 6346 |
// 削除対象の中にBindersが入っている場合は、削除できない。 |
affectedIIDs = new itemid_t[iidsLen]; |
| 6347 |
for ( int i = 0; i < descXIDLen; i++ ){ |
string xid_str = getCsvStr( descXID, descXIDLen ); |
| 6348 |
if ( descXID[i] == item::IID_BINDERS ){ |
sql = "select item_id from " + dbprefix + "_xoonips_index_item_link " |
| 6349 |
setLastErrorString( "in deleteIndex: target index contains Binders." ); |
"where certify_state=" + unsignedIntToString(index::CERTIFIED) + |
| 6350 |
return RES_ERROR; |
" and index_id in ( 0 " + xid_str + ") "; |
| 6351 |
} |
sqlexec_t s( "deleteIndex", sql, &result ); |
| 6352 |
} |
if ( s.getSqlcode() != SQL_SUCCESS ) |
| 6353 |
|
return result; |
| 6354 |
|
|
| 6355 |
|
SQLUINTEGER iid = 0; |
| 6356 |
|
SQLLEN cbIID = 0; |
| 6357 |
|
SQLBindCol( s.getHstmt(), 1, SQL_C_ULONG, &iid , 0, &cbIID ); |
| 6358 |
|
|
| 6359 |
|
for ( affectedIIDsLen = 0; affectedIIDsLen < iidsLen && ( SQLFetch( s.getHstmt() ) == SQL_SUCCESS ); affectedIIDsLen++ ){ |
| 6360 |
|
affectedIIDs[affectedIIDsLen] = iid; |
| 6361 |
|
} |
| 6362 |
|
} |
| 6363 |
|
|
| 6364 |
|
SQLRETURN sqlcode; |
| 6365 |
|
SQLHANDLE hstmt = NULL; |
| 6366 |
|
if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) { |
| 6367 |
|
result = RES_OK; |
| 6368 |
|
string strParentXID = unsignedIntToString( index->getParentIndexID() ); |
| 6369 |
|
for ( int i = descXIDLen-1; i >= 0; i-- ){ // 逆方向にして、途中で失敗した場合の惨事を防ぐ。descXIDは幅優先探索順に並んでいるので。 |
| 6370 |
|
string strXID = unsignedIntToString(descXID[i]); |
| 6371 |
|
string linkTable = dbprefix + "_xoonips_index_item_link"; |
| 6372 |
|
|
| 6373 |
SQLRETURN sqlcode; |
// descXID[i] のアイテムの中で、被参照数が1のものを列挙 → 迷子にならないように移動 |
| 6374 |
SQLHANDLE hstmt = NULL; |
// HAVINGを使うべき? "select item_id, count(*) as v1, sum(index_id=$index_id) as v2 from $link_table having v1=1 and v2=1" |
| 6375 |
if( ( sqlcode = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ) == SQL_SUCCESS ) { |
// しかしsum内に<predicate>を書いてもいいのだろうか? 代わりにnullifとcoalesceならsqliteは通るが・・・ |
| 6376 |
result = RES_OK; |
// → 互換性の高い方法がよくわからないので、とりあえず自己joinにする。 |
| 6377 |
string strParentXID = unsignedIntToString( index->getParentIndexID() ); |
string sql( "SELECT t1.index_item_link_id " |
| 6378 |
for ( int i = descXIDLen-1; i >= 0; i-- ){ // 逆方向にして、途中で失敗した場合の惨事を防ぐ。descXIDは幅優先探索順に並んでいるので。 |
" FROM " + linkTable + " AS t1 " |
| 6379 |
string strXID = unsignedIntToString(descXID[i]); |
" LEFT JOIN " + linkTable + " AS t2 ON t1.item_id = t2.item_id and t2.index_id <> t1.index_id " |
| 6380 |
string linkTable = dbprefix + "_xoonips_index_item_link"; |
" WHERE t1.index_id=" + strXID + " and t2.item_id is NULL" ); |
| 6381 |
|
if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){ |
| 6382 |
// descXID[i] のアイテムの中で、被参照数が1のものを列挙 → 迷子にならないように移動 |
SQLUINTEGER sLinkID = 0; |
| 6383 |
// HAVINGを使うべき? "select item_id, count(*) as v1, sum(index_id=$index_id) as v2 from $link_table having v1=1 and v2=1" |
SQLLEN len = 0; |
| 6384 |
// しかしsum内に<predicate>を書いてもいいのだろうか? 代わりにnullifとcoalesceならsqliteは通るが・・・ |
SQLBindCol( hstmt, 1, SQL_C_ULONG, &sLinkID, 0, &len ); |
| 6385 |
// → 互換性の高い方法がよくわからないので、とりあえず自己joinにする。 |
while ( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){ |
| 6386 |
string sql( "SELECT t1.index_item_link_id " |
string sql2( "UPDATE " + linkTable + " set index_id= " + strParentXID + " where index_item_link_id = " + unsignedIntToString(sLinkID) ); |
| 6387 |
" FROM " + linkTable + " AS t1 " |
result = querySimple( "deleteIndex", sql2 ); |
| 6388 |
" LEFT JOIN " + linkTable + " AS t2 ON t1.item_id = t2.item_id and t2.index_id <> t1.index_id " |
if( result != RES_OK ) |
|
" WHERE t1.index_id=" + strXID + " and t2.item_id is NULL" ); |
|
|
if( ( sqlcode = SQLExecDirect( hstmt, (SQLCHAR*)sql.c_str(), sql.length() ) ) == SQL_SUCCESS ){ |
|
|
SQLUINTEGER sLinkID = 0; |
|
|
SQLLEN len = 0; |
|
|
SQLBindCol( hstmt, 1, SQL_C_ULONG, &sLinkID, 0, &len ); |
|
|
while ( ( sqlcode = SQLFetch( hstmt ) ) == SQL_SUCCESS ){ |
|
|
string sql2( "UPDATE " + linkTable + " set index_id= " + strParentXID + " where index_item_link_id = " + unsignedIntToString(sLinkID) ); |
|
|
result = querySimple( "deleteIndex", sql2 ); |
|
|
if( result != RES_OK ) |
|
|
break; |
|
|
} |
|
|
if ( result != RES_OK ) |
|
|
break; |
|
|
}else{ |
|
|
string s( "SQLExecDirect in deleteIndex" ); |
|
|
s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode ); |
|
|
s += "sql="; |
|
|
s += string( sql ); |
|
|
setLastErrorString( s.c_str( ) ); |
|
|
result = RES_DB_QUERY_ERROR; |
|
| 6389 |
break; |
break; |
|
} |
|
|
|
|
|
// descXID[i] のアイテムを全て削除 |
|
|
sql = "DELETE from " + linkTable + " where index_id=" + strXID; |
|
|
result = querySimple( functionName, sql ); |
|
|
if ( result == RES_OK ){ |
|
|
// descXID[i] を削除 |
|
|
sql = "DELETE from " + dbprefix + "_xoonips_item_basic where item_id =" + strXID; |
|
|
result = querySimple( functionName, sql ); |
|
|
if ( result == RES_OK ){ |
|
|
sql = "DELETE from " + dbprefix + "_xoonips_index where index_id=" + strXID; |
|
|
result = querySimple( functionName, sql ); |
|
|
} |
|
|
} |
|
| 6390 |
} |
} |
| 6391 |
|
if ( result != RES_OK ) |
| 6392 |
|
break; |
| 6393 |
}else{ |
}else{ |
| 6394 |
string s( "SQLAllocHandle in deleteIndex" ); |
string s( "SQLExecDirect in deleteIndex" ); |
| 6395 |
s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode ); |
s += odbcDiagString( SQL_HANDLE_STMT, hstmt, sqlcode ); |
| 6396 |
|
s += "sql="; |
| 6397 |
|
s += string( sql ); |
| 6398 |
setLastErrorString( s.c_str( ) ); |
setLastErrorString( s.c_str( ) ); |
| 6399 |
result = RES_ERROR; |
result = RES_DB_QUERY_ERROR; |
| 6400 |
|
break; |
| 6401 |
} |
} |
| 6402 |
|
|
| 6403 |
freeIndexID( descXID ); |
// descXID[i] のアイテムを全て削除 |
| 6404 |
|
sql = "DELETE from " + linkTable + " where index_id=" + strXID; |
| 6405 |
|
result = querySimple( functionName, sql ); |
| 6406 |
|
if ( result == RES_OK ){ |
| 6407 |
|
// descXID[i] を削除 |
| 6408 |
|
sql = "DELETE from " + dbprefix + "_xoonips_item_basic where item_id =" + strXID; |
| 6409 |
|
result = querySimple( functionName, sql ); |
| 6410 |
|
if ( result == RES_OK ){ |
| 6411 |
|
sql = "DELETE from " + dbprefix + "_xoonips_index where index_id=" + strXID; |
| 6412 |
|
result = querySimple( functionName, sql ); |
| 6413 |
|
} |
| 6414 |
|
} |
| 6415 |
} |
} |
| 6416 |
|
|
| 6417 |
|
// 影響を受けたはずのアイテムを insertMetadataEventAutoする |
| 6418 |
|
for ( int i = 0; i < affectedIIDsLen; i++ ){ |
| 6419 |
|
insertMetadataEventAuto( affectedIIDs[i] ); |
| 6420 |
|
} |
| 6421 |
|
|
| 6422 |
|
}else{ |
| 6423 |
|
string s( "SQLAllocHandle in deleteIndex" ); |
| 6424 |
|
s += odbcDiagString( SQL_HANDLE_DBC, hdbc, sqlcode ); |
| 6425 |
|
setLastErrorString( s.c_str( ) ); |
| 6426 |
|
result = RES_ERROR; |
| 6427 |
} |
} |
| 6428 |
|
|
| 6429 |
|
return result; |
| 6430 |
|
} |
| 6431 |
|
|
| 6432 |
|
/** |
| 6433 |
|
* |
| 6434 |
|
* インデックスキーワードを削除する |
| 6435 |
|
* |
| 6436 |
|
* @param sid セッションID |
| 6437 |
|
* @param xid 削除するインデックスキーワード |
| 6438 |
|
* @return RES_OK 成功 |
| 6439 |
|
* |
| 6440 |
|
*/ |
| 6441 |
|
result_t deleteIndex( sessionid_t sid, indexid_t xid ) |
| 6442 |
|
{ |
| 6443 |
|
const index_t *index = 0; |
| 6444 |
|
indexid_t *descXID = 0; |
| 6445 |
|
itemid_t *affectedIIDs = 0; |
| 6446 |
|
result_t result = deleteIndexInternal( sid, xid, index, descXID, affectedIIDs ); |
| 6447 |
|
if ( index ) freeIndex( index ); |
| 6448 |
|
if ( descXID ) delete[] descXID; |
| 6449 |
|
if ( affectedIIDs ) delete[] affectedIIDs; |
| 6450 |
return result; |
return result; |
| 6451 |
} |
} |
| 6452 |
|
|
| 7301 |
ret = sessionID2UID( sid, &uid ); |
ret = sessionID2UID( sid, &uid ); |
| 7302 |
if( ret != RES_OK ) return ret; |
if( ret != RES_OK ) return ret; |
| 7303 |
|
|
| 7304 |
// 文字列 ',' . implode( ',', iids ) を作成 |
string iids_str = getCsvStr( iids, iidsLen ); |
|
char *buf = new char[(sizeof(int)*3+1)*iidsLen+1]; |
|
|
buf[0] = '\0'; |
|
|
char *p = buf; |
|
|
for ( int i = 0; i < iidsLen; i++ ){ |
|
|
int len = sprintf( p, ",%u", iids[i] ); |
|
|
p += len; |
|
|
} |
|
|
string iids_str(buf); |
|
|
delete[] buf; |
|
|
|
|
| 7305 |
|
|
| 7306 |
string sql = |
string sql = |
| 7307 |
" select ti.item_id, count(tx.index_id) " |
" select ti.item_id, count(tx.index_id) " |
| 8078 |
return ret; |
return ret; |
| 8079 |
} |
} |
| 8080 |
|
|
| 8081 |
|
static result_t insertMetadataEvent( metadataevent_t me, itemid_t iid ) |
| 8082 |
|
{ |
| 8083 |
|
string sql; |
| 8084 |
|
|
| 8085 |
|
if ( me == ME_CREATED ){ |
| 8086 |
|
sql = "replace " + dbprefix + "_xoonips_item_status " |
| 8087 |
|
" ( item_id, created_timestamp, modified_timestamp, deleted_timestamp, is_deleted ) values " |
| 8088 |
|
" ( " + unsignedIntToString(iid) + ", unix_timestamp(now()), NULL, NULL, 0 )"; |
| 8089 |
|
} |
| 8090 |
|
else if ( me == ME_MODIFIED ){ |
| 8091 |
|
sql = "update " + dbprefix + "_xoonips_item_status " |
| 8092 |
|
" set modified_timestamp=unix_timestamp(now()), is_deleted=0 where item_id=" + unsignedIntToString(iid); |
| 8093 |
|
} |
| 8094 |
|
else if ( me == ME_DELETED ){ |
| 8095 |
|
sql = "update " + dbprefix + "_xoonips_item_status " |
| 8096 |
|
" set deleted_timestamp=unix_timestamp(now()), is_deleted=1 where item_id=" + unsignedIntToString(iid); |
| 8097 |
|
} |
| 8098 |
|
else { |
| 8099 |
|
return RES_ERROR; |
| 8100 |
|
} |
| 8101 |
|
|
| 8102 |
|
return querySimple( "insertMetadataEvent", sql ); |
| 8103 |
|
} |
| 8104 |
|
|
| 8105 |
|
static result_t getMetadataEvent( itemid_t iid, itemstatus_t *status ) |
| 8106 |
|
{ |
| 8107 |
|
result_t ret = RES_ERROR; |
| 8108 |
|
|
| 8109 |
|
// allocate events[] |
| 8110 |
|
string sql = "select created_timestamp, modified_timestamp, deleted_timestamp, is_deleted from " |
| 8111 |
|
+ dbprefix + "_xoonips_item_status where item_id=" + unsignedIntToString(iid); |
| 8112 |
|
sqlexec_t s( "getMetadataEvent", sql, &ret ); |
| 8113 |
|
if ( s.getSqlcode() == SQL_SUCCESS ){ |
| 8114 |
|
SQLUINTEGER created, modified, deleted, isDeleted = 0; |
| 8115 |
|
SQLLEN cbCreated = 0, cbModified = 0, cbDeleted = 0, cbIsDeleted = 0; |
| 8116 |
|
SQLBindCol( s.getHstmt(), 1, SQL_C_ULONG, &created , 0, &cbCreated ); |
| 8117 |
|
SQLBindCol( s.getHstmt(), 2, SQL_C_ULONG, &modified , 0, &cbModified ); |
| 8118 |
|
SQLBindCol( s.getHstmt(), 3, SQL_C_ULONG, &deleted , 0, &cbDeleted ); |
| 8119 |
|
SQLBindCol( s.getHstmt(), 4, SQL_C_ULONG, &isDeleted, 0, &cbIsDeleted ); |
| 8120 |
|
|
| 8121 |
|
if ( SQLFetch( s.getHstmt() ) == SQL_SUCCESS ){ |
| 8122 |
|
status->createdTimestamp = created; |
| 8123 |
|
status->modifiedTimestamp = modified; |
| 8124 |
|
status->deletedTimestamp = deleted; |
| 8125 |
|
status->isDeleted = isDeleted; |
| 8126 |
|
ret = RES_OK; |
| 8127 |
|
} |
| 8128 |
|
else { |
| 8129 |
|
ret = RES_NO_SUCH_ITEM; |
| 8130 |
|
} |
| 8131 |
|
} |
| 8132 |
|
return ret; |
| 8133 |
|
} |
| 8134 |
|
|
| 8135 |
|
/** 適切にinsertMeatadataEventを行う |
| 8136 |
|
* repository item |
| 8137 |
|
* is_deleted==0 && public : isCreate ? ME_CREATED : ME_MODIFIED; |
| 8138 |
|
* is_deleted==0 && nonpublic : ME_DELETED |
| 8139 |
|
* is_deleted!=0 && public : ME_CREATED |
| 8140 |
|
* is_deleted!=0 && nonpubic : - |
| 8141 |
|
* |
| 8142 |
|
*/ |
| 8143 |
|
static result_t insertMetadataEventAuto( itemid_t iid, bool isCreate ) |
| 8144 |
|
{ |
| 8145 |
|
itemstatus_t is; |
| 8146 |
|
result_t res = getMetadataEvent( iid, &is ); |
| 8147 |
|
if ( res != RES_OK ){ |
| 8148 |
|
if ( res == RES_NO_SUCH_ITEM ) |
| 8149 |
|
is.isDeleted = 1; |
| 8150 |
|
else |
| 8151 |
|
return res; |
| 8152 |
|
} |
| 8153 |
|
|
| 8154 |
|
bool isPublic = getItemPermission( session::SID_GUEST, iid, item::OP_READ ); |
| 8155 |
|
|
| 8156 |
|
metadataevent_t me; |
| 8157 |
|
if ( is.isDeleted == 0 ){ |
| 8158 |
|
if ( isPublic ) |
| 8159 |
|
me = isCreate ? ME_CREATED : ME_MODIFIED; |
| 8160 |
|
else |
| 8161 |
|
me = ME_DELETED; |
| 8162 |
|
} |
| 8163 |
|
else { |
| 8164 |
|
if ( isPublic ) |
| 8165 |
|
me = ME_CREATED; |
| 8166 |
|
else |
| 8167 |
|
return RES_OK; |
| 8168 |
|
} |
| 8169 |
|
|
| 8170 |
|
return insertMetadataEvent( me, iid ); |
| 8171 |
|
} |
| 8172 |
|
|
| 8173 |
|
|
| 8174 |
|
|
| 8175 |
|
|
| 8176 |
|
result_t updateItemStatus() |
| 8177 |
|
{ |
| 8178 |
|
result_t ret = RES_ERROR; |
| 8179 |
|
|
| 8180 |
|
if ( isGuestEnabled() ){ |
| 8181 |
|
{ |
| 8182 |
|
// アイテムが公開済みで、item_statusが削除または非存在のものを修正 |
| 8183 |
|
string sql = "select distinct txil.item_id, tis.is_deleted " |
| 8184 |
|
" from " + dbprefix + "_xoonips_index as tx, " |
| 8185 |
|
+ dbprefix + "_xoonips_index_item_link as txil " |
| 8186 |
|
" left join " + dbprefix + "_xoonips_item_status as tis on txil.item_id = tis.item_id " |
| 8187 |
|
" where tx.index_id=txil.index_id " |
| 8188 |
|
" and txil.certify_state = " + unsignedIntToString( index::CERTIFIED ) + |
| 8189 |
|
" and tx.open_level = " + unsignedIntToString( index::OL_PUBLIC ); |
| 8190 |
|
sqlexec_t s( "updateItemStatus", sql, &ret ); |
| 8191 |
|
if ( s.getSqlcode() == SQL_SUCCESS ){ |
| 8192 |
|
SQLUINTEGER iid = 0, isDeleted = 0; |
| 8193 |
|
SQLLEN cbIID = 0, cbIsDeleted = 0; |
| 8194 |
|
SQLBindCol( s.getHstmt(), 1, SQL_C_ULONG, &iid , 0, &cbIID ); |
| 8195 |
|
SQLBindCol( s.getHstmt(), 2, SQL_C_ULONG, &isDeleted , 0, &cbIsDeleted ); |
| 8196 |
|
|
| 8197 |
|
while ( SQLFetch( s.getHstmt() ) == SQL_SUCCESS ){ |
| 8198 |
|
string sql; |
| 8199 |
|
if ( cbIsDeleted == SQL_NULL_DATA ) |
| 8200 |
|
sql = "insert into " + dbprefix + "_xoonips_item_status " |
| 8201 |
|
"( item_id, created_timestamp, is_deleted ) values " |
| 8202 |
|
"( " + unsignedIntToString(iid) + ", unix_timestamp(now()), 0 )"; |
| 8203 |
|
else |
| 8204 |
|
sql = "update "+ dbprefix + "_xoonips_item_status " |
| 8205 |
|
" set created_timestamp=unix_timestamp(now()), is_deleted=0 " |
| 8206 |
|
" where item_id=" + unsignedIntToString(iid); |
| 8207 |
|
ret = querySimple( "updateItemStatus", sql ); |
| 8208 |
|
if ( ret ) return ret; |
| 8209 |
|
} |
| 8210 |
|
} |
| 8211 |
|
else return ret; |
| 8212 |
|
} |
| 8213 |
|
{ |
| 8214 |
|
// アイテムが非公開で、item_status.is_deleted=0のものを修正 |
| 8215 |
|
string sql = "select tis.item_id " |
| 8216 |
|
" from " + dbprefix + "_xoonips_item_status as tis " |
| 8217 |
|
" left join " + dbprefix + "_xoonips_index_item_link as tl on tl.item_id = tis.item_id and certify_state = " + unsignedIntToString(index::CERTIFIED) + |
| 8218 |
|
" left join " + dbprefix + "_xoonips_index as tx on tx.index_id =tl.index_id and tx.open_level = " + unsignedIntToString(index::OL_PUBLIC) + |
| 8219 |
|
" where is_deleted=0 and tx.index_id is NULL "; |
| 8220 |
|
sqlexec_t s( "updateItemStatus", sql, &ret ); |
| 8221 |
|
if ( s.getSqlcode() == SQL_SUCCESS ){ |
| 8222 |
|
SQLUINTEGER iid = 0; |
| 8223 |
|
SQLLEN cbIID = 0; |
| 8224 |
|
SQLBindCol( s.getHstmt(), 1, SQL_C_ULONG, &iid , 0, &cbIID ); |
| 8225 |
|
|
| 8226 |
|
while ( SQLFetch( s.getHstmt() ) == SQL_SUCCESS ){ |
| 8227 |
|
string sql; |
| 8228 |
|
sql = "update " + dbprefix + "_xoonips_item_status " |
| 8229 |
|
" set is_deleted=1, deleted_timestamp=unix_timestamp(now()) " |
| 8230 |
|
" where item_id=" + unsignedIntToString(iid); |
| 8231 |
|
ret = querySimple( "updateItemStatus", sql ); |
| 8232 |
|
if ( ret ) return ret; |
| 8233 |
|
} |
| 8234 |
|
} |
| 8235 |
|
else return ret; |
| 8236 |
|
} |
| 8237 |
|
} |
| 8238 |
|
else { |
| 8239 |
|
string sql = "delete from " + dbprefix + "_xoonips_item_status"; |
| 8240 |
|
ret = querySimple( "updateItemStatus", sql ); |
| 8241 |
|
} |
| 8242 |
|
return ret; |
| 8243 |
|
} |
| 8244 |
|
|
| 8245 |
|
/** item_statusテーブルをクリアしてupdateItemStatusを行う */ |
| 8246 |
|
result_t refreshItemStatus() |
| 8247 |
|
{ |
| 8248 |
|
string sql = "delete from " + dbprefix + "_xoonips_item_status"; |
| 8249 |
|
result_t ret = querySimple( "refreshItemStatus", sql ); |
| 8250 |
|
if ( ret ) return ret; |
| 8251 |
|
return updateItemStatus(); |
| 8252 |
|
} |
| 8253 |
|
|
| 8254 |
|
/** selective harvesting |
| 8255 |
|
* @param from, until 選択範囲 |
| 8256 |
|
* @param startIID startIID<=item_idであるようなitem_idのみを得る |
| 8257 |
|
* @param limit 返すitem_idの個数の上限 |
| 8258 |
|
* @param iids item_idを返す配列 item_idの小さいものから配列に入る |
| 8259 |
|
* @param iidsLen iidsの長さ |
| 8260 |
|
*/ |
| 8261 |
|
result_t selectiveHarvesting( time_t from, time_t until, int startIID, int limit, itemid_t **iids, int *iidsLen ) |
| 8262 |
|
{ |
| 8263 |
|
result_t ret = RES_ERROR; |
| 8264 |
|
if ( limit < 0 ) return RES_ERROR; |
| 8265 |
|
|
| 8266 |
|
string sql = "select item_id " |
| 8267 |
|
" from " + dbprefix + "_xoonips_item_status " |
| 8268 |
|
" where " + unsignedIntToString(from) + " <= unix_timestamp(timestamp) " |
| 8269 |
|
" and unix_timestamp(timestamp) <= " + unsignedIntToString(until) + |
| 8270 |
|
" and item_id >= " + unsignedIntToString(startIID) + |
| 8271 |
|
" limit " + unsignedIntToString(limit); |
| 8272 |
|
sqlexec_t s( "updateItemStatus", sql, &ret ); |
| 8273 |
|
//setLastErrorString( "selectiveHarvesting..." ); |
| 8274 |
|
//setLastErrorString( sql.c_str( ) ); |
| 8275 |
|
if ( s.getSqlcode() == SQL_SUCCESS ){ |
| 8276 |
|
SQLUINTEGER iid = 0; |
| 8277 |
|
SQLLEN cbIID = 0; |
| 8278 |
|
SQLBindCol( s.getHstmt(), 1, SQL_C_ULONG, &iid , 0, &cbIID ); |
| 8279 |
|
|
| 8280 |
|
*iids = new itemid_t[limit]; |
| 8281 |
|
for ( *iidsLen = 0; *iidsLen < limit && SQLFetch( s.getHstmt() ) == SQL_SUCCESS; (*iidsLen)++ ){ |
| 8282 |
|
(*iids)[*iidsLen] = iid; |
| 8283 |
|
} |
| 8284 |
|
ret = RES_OK; |
| 8285 |
|
} |
| 8286 |
|
return ret; |
| 8287 |
|
} |
| 8288 |
|
|
| 8289 |
|
|