From: <asf...@us...> - 2010-06-05 00:48:12
|
Revision: 51205 http://firebird.svn.sourceforge.net/firebird/?rev=51205&view=rev Author: asfernandes Date: 2010-06-05 00:48:06 +0000 (Sat, 05 Jun 2010) Log Message: ----------- Port from CVS Vlad's fixes for CORE-3015, CORE-3016 and CORE-3017 Modified Paths: -------------- firebird/trunk/src/jrd/DatabaseSnapshot.cpp firebird/trunk/src/jrd/cch.cpp firebird/trunk/src/jrd/isc.h firebird/trunk/src/jrd/isc_s_proto.h firebird/trunk/src/jrd/isc_sync.cpp firebird/trunk/src/jrd/trace/TraceConfigStorage.cpp Modified: firebird/trunk/src/jrd/DatabaseSnapshot.cpp =================================================================== --- firebird/trunk/src/jrd/DatabaseSnapshot.cpp 2010-06-05 00:26:55 UTC (rev 51204) +++ firebird/trunk/src/jrd/DatabaseSnapshot.cpp 2010-06-05 00:48:06 UTC (rev 51205) @@ -96,6 +96,9 @@ { // scope DumpGuard guard(this); cleanup(); + + if (base->used == sizeof(Header)) + ISC_remove_map_file(&handle); } #ifdef WIN_NT Modified: firebird/trunk/src/jrd/cch.cpp =================================================================== --- firebird/trunk/src/jrd/cch.cpp 2010-06-05 00:26:55 UTC (rev 51204) +++ firebird/trunk/src/jrd/cch.cpp 2010-06-05 00:48:06 UTC (rev 51205) @@ -276,6 +276,9 @@ { Database::SyncGuard dsGuard(dbb, true); + if (dbb->dbb_flags & DBB_not_in_use) + return 0; + Lock* const lock = dbb->dbb_lock; // Since this routine will be called asynchronously, Modified: firebird/trunk/src/jrd/isc.h =================================================================== --- firebird/trunk/src/jrd/isc.h 2010-06-05 00:26:55 UTC (rev 51204) +++ firebird/trunk/src/jrd/isc.h 2010-06-05 00:48:06 UTC (rev 51205) @@ -105,6 +105,7 @@ UCHAR *sh_mem_address; ULONG sh_mem_length_mapped; SLONG sh_mem_handle; + TEXT sh_mem_name[MAXPATHLEN]; }; #endif // UNIX Modified: firebird/trunk/src/jrd/isc_s_proto.h =================================================================== --- firebird/trunk/src/jrd/isc_s_proto.h 2010-06-05 00:26:55 UTC (rev 51204) +++ firebird/trunk/src/jrd/isc_s_proto.h 2010-06-05 00:48:06 UTC (rev 51205) @@ -72,5 +72,6 @@ void ISC_unmap_file(Firebird::Arg::StatusVector&, struct sh_mem*); void ISC_remove_map_file(const TEXT* filename); +void ISC_remove_map_file(const struct sh_mem*); #endif // JRD_ISC_S_PROTO_H Modified: firebird/trunk/src/jrd/isc_sync.cpp =================================================================== --- firebird/trunk/src/jrd/isc_sync.cpp 2010-06-05 00:26:55 UTC (rev 51204) +++ firebird/trunk/src/jrd/isc_sync.cpp 2010-06-05 00:48:06 UTC (rev 51205) @@ -1678,14 +1678,21 @@ void ISC_remove_map_file(const TEXT* filename) { +#ifndef WIN_NT TEXT expanded_filename[MAXPATHLEN]; gds__prefix_lock(expanded_filename, filename); // We can't do much (specially in dtors) when it fails // therefore do not check for errors - at least it's just /tmp. unlink(expanded_filename); +#endif // WIN_NT } +void ISC_remove_map_file(const struct sh_mem* shmem_data) +{ + ISC_remove_map_file(shmem_data->sh_mem_name); +} + #ifdef UNIX UCHAR* ISC_map_file(Arg::StatusVector& statusVector, @@ -1821,6 +1828,7 @@ shmem_data->sh_mem_address = address; shmem_data->sh_mem_length_mapped = length; shmem_data->sh_mem_handle = fd; + strcpy(shmem_data->sh_mem_name, filename); #ifdef USE_SYS5SEMAPHORE // register mapped file @@ -1923,18 +1931,21 @@ * routine (if given) or punt (leaving the file unmapped). * **************************************/ - HANDLE file_handle, event_handle; + HANDLE file_handle; + HANDLE event_handle = 0; int retry_count = 0; TEXT expanded_filename[MAXPATHLEN]; gds__prefix_lock(expanded_filename, filename); const bool trunc_flag = (length != 0); + bool init_flag = false; // retry to attach to mmapped file if the process initializing dies during initialization. retry: - retry_count++; + if (retry_count++ > 0) + THREAD_SLEEP(10); file_handle = CreateFile(expanded_filename, GENERIC_READ | GENERIC_WRITE, @@ -1943,15 +1954,19 @@ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + DWORD err = GetLastError(); if (file_handle == INVALID_HANDLE_VALUE) { + if (err == ERROR_SHARING_VIOLATION) + goto retry; + error(statusVector, "CreateFile", GetLastError()); return NULL; } // Check if file already exists - const bool file_exists = (GetLastError() == ERROR_ALREADY_EXISTS); + const bool file_exists = (err == ERROR_ALREADY_EXISTS); // Create an event that can be used to determine if someone has already // initialized shared memory. @@ -1964,22 +1979,25 @@ return NULL; } - event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, object_name); - if (!event_handle) + if (!init_flag) { - error(statusVector, "CreateEvent", GetLastError()); - CloseHandle(file_handle); - return NULL; - } + event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, object_name); + if (!event_handle) + { + error(statusVector, "CreateEvent", GetLastError()); + CloseHandle(file_handle); + return NULL; + } - const bool init_flag = (GetLastError() != ERROR_ALREADY_EXISTS); + init_flag = (GetLastError() != ERROR_ALREADY_EXISTS); - if (init_flag && !init_routine) - { - CloseHandle(event_handle); - CloseHandle(file_handle); - statusVector << Arg::Gds(isc_unavailable); - return NULL; + if (init_flag && !init_routine) + { + CloseHandle(event_handle); + CloseHandle(file_handle); + statusVector << Arg::Gds(isc_unavailable); + return NULL; + } } if (length == 0) @@ -2016,7 +2034,7 @@ CloseHandle(event_handle); if (retry_count > 10) { - error(statusVector, "WaitForSingleObject", GetLastError()); + error(statusVector, "WaitForSingleObject", 0); return NULL; } goto retry; @@ -2040,6 +2058,14 @@ { const DWORD err = GetLastError(); + if ((err == ERROR_SHARING_VIOLATION) || (err == ERROR_FILE_NOT_FOUND && fdw_create == TRUNCATE_EXISTING)) + { + if (!init_flag) { + CloseHandle(event_handle); + } + goto retry; + } + if (err == ERROR_USER_MAPPED_FILE && init_flag && file_exists && trunc_flag) statusVector << Arg::Gds(isc_instance_conflict); else @@ -3388,11 +3414,18 @@ TEXT expanded_filename[MAXPATHLEN]; gds__prefix_lock(expanded_filename, shmem_data->sh_mem_name); - if (!DeleteFile(expanded_filename)) - { - error(statusVector, "DeleteFile", GetLastError()); - return; - } + + // Delete file only if it is not used by anyone else + HANDLE hFile = CreateFile(expanded_filename, + DELETE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); } #endif Modified: firebird/trunk/src/jrd/trace/TraceConfigStorage.cpp =================================================================== --- firebird/trunk/src/jrd/trace/TraceConfigStorage.cpp 2010-06-05 00:26:55 UTC (rev 51204) +++ firebird/trunk/src/jrd/trace/TraceConfigStorage.cpp 2010-06-05 00:48:06 UTC (rev 51205) @@ -137,6 +137,8 @@ { unlink(m_base->cfg_file_name); memset(m_base->cfg_file_name, 0, sizeof(m_base->cfg_file_name)); + + ISC_remove_map_file(&m_handle); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-06-10 16:08:26
|
Revision: 51241 http://firebird.svn.sourceforge.net/firebird/?rev=51241&view=rev Author: asfernandes Date: 2010-06-10 16:08:18 +0000 (Thu, 10 Jun 2010) Log Message: ----------- Fix debug code Modified Paths: -------------- firebird/trunk/src/jrd/common.h firebird/trunk/src/jrd/gds.cpp Modified: firebird/trunk/src/jrd/common.h =================================================================== --- firebird/trunk/src/jrd/common.h 2010-06-10 08:47:12 UTC (rev 51240) +++ firebird/trunk/src/jrd/common.h 2010-06-10 16:08:18 UTC (rev 51241) @@ -800,15 +800,14 @@ #define IMPLEMENT_TRACE_ROUTINE(routine, subsystem) \ void routine(const char* message, ...) \ { \ - static const char name_facility[] = subsystem ","; \ - char buffer[1000]; \ - strcpy(buffer, name_facility); \ - char *ptr = buffer + sizeof(name_facility) - 1; \ + Firebird::string format(subsystem ","); \ + format += message; \ + Firebird::string buffer; \ va_list params; \ va_start(params, message); \ - VSNPRINTF(ptr, sizeof(buffer) - sizeof(name_facility), message, params); \ + buffer.vprintf(format.c_str(), params); \ va_end(params); \ - gds__trace(buffer); \ + gds__trace(buffer.c_str()); \ } #ifdef DEV_BUILD Modified: firebird/trunk/src/jrd/gds.cpp =================================================================== --- firebird/trunk/src/jrd/gds.cpp 2010-06-10 08:47:12 UTC (rev 51240) +++ firebird/trunk/src/jrd/gds.cpp 2010-06-10 16:08:18 UTC (rev 51241) @@ -1095,7 +1095,7 @@ * This function tries to be async-signal safe * **************************************/ - const time_t now = time((time_t *)0); // is specified in POSIX to be signal-safe + const time_t now = time(NULL); // is specified in POSIX to be signal-safe // 07 Sept 2003, Nickolay Samofatov. // Since we cannot call ctime/localtime_r or anything else like this from @@ -1111,7 +1111,7 @@ today.tm_min = rem / 60; today.tm_sec = rem % 60; - char buffer[1024]; // 1K should be enough for the trace message + char buffer[BUFFER_MEDIUM]; char* p = buffer; gds__ulstr(p, today.tm_year + 1900, 4, '0'); @@ -1144,11 +1144,13 @@ gds__ulstr(p, getThreadId(), 5, ' '); p += 5; *p++ = ' '; - strcpy(p, text); - p += strlen(p); - strcat(p, "\n"); - p += strlen(p); - gds__trace_raw(buffer, p - buffer); + *p = '\0'; + + Firebird::string s(p); + s += text; + s += "\n"; + + gds__trace_raw(s.c_str(), s.length()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ale...@us...> - 2010-06-15 12:27:39
|
Revision: 51253 http://firebird.svn.sourceforge.net/firebird/?rev=51253&view=rev Author: alexpeshkoff Date: 2010-06-15 12:27:33 +0000 (Tue, 15 Jun 2010) Log Message: ----------- Fixed CORE-3024: Error "no current record for fetch operation" after ALTER VIEW (and a lot of other possible inconsistencies) Modified Paths: -------------- firebird/trunk/src/jrd/Relation.h firebird/trunk/src/jrd/cmp.cpp firebird/trunk/src/jrd/dfw.epp firebird/trunk/src/jrd/lck.cpp firebird/trunk/src/jrd/lck.h firebird/trunk/src/jrd/met.epp Modified: firebird/trunk/src/jrd/Relation.h =================================================================== --- firebird/trunk/src/jrd/Relation.h 2010-06-15 12:00:00 UTC (rev 51252) +++ firebird/trunk/src/jrd/Relation.h 2010-06-15 12:27:33 UTC (rev 51253) @@ -202,6 +202,7 @@ Lock* rel_existence_lock; // existence lock, if any Lock* rel_partners_lock; // partners lock + Lock* rel_rescan_lock; // lock forcing relation to be scanned IndexLock* rel_index_locks; // index existence locks IndexBlock* rel_index_blocks; // index blocks for caching index info trig_vec* rel_pre_erase; // Pre-operation erase trigger Modified: firebird/trunk/src/jrd/cmp.cpp =================================================================== --- firebird/trunk/src/jrd/cmp.cpp 2010-06-15 12:00:00 UTC (rev 51252) +++ firebird/trunk/src/jrd/cmp.cpp 2010-06-15 12:27:33 UTC (rev 51253) @@ -1750,6 +1750,11 @@ LCK_release(tdbb, relation->rel_partners_lock); relation->rel_flags |= REL_check_partners; } + if (relation->rel_rescan_lock) + { + LCK_release(tdbb, relation->rel_rescan_lock); + relation->rel_flags &= ~REL_scanned; + } for (IndexLock* index = relation->rel_index_locks; index; index = index->idl_next) { if (index->idl_lock) Modified: firebird/trunk/src/jrd/dfw.epp =================================================================== --- firebird/trunk/src/jrd/dfw.epp 2010-06-15 12:00:00 UTC (rev 51252) +++ firebird/trunk/src/jrd/dfw.epp 2010-06-15 12:27:33 UTC (rev 51253) @@ -4185,6 +4185,9 @@ if (relation->rel_partners_lock) { LCK_release(tdbb, relation->rel_partners_lock); } + if (relation->rel_rescan_lock) { + LCK_release(tdbb, relation->rel_rescan_lock); + } // Mark relation in the cache as dropped relation->rel_flags |= REL_deleted; @@ -5456,6 +5459,10 @@ relation->rel_flags &= ~REL_scanned; DFW_post_work(transaction, dfw_scan_relation, NULL, relation->rel_id); + // signal others about new format presence + LCK_lock(tdbb, relation->rel_rescan_lock, LCK_EX, LCK_WAIT); + LCK_release(tdbb, relation->rel_rescan_lock); + break; } Modified: firebird/trunk/src/jrd/lck.cpp =================================================================== --- firebird/trunk/src/jrd/lck.cpp 2010-06-15 12:00:00 UTC (rev 51252) +++ firebird/trunk/src/jrd/lck.cpp 2010-06-15 12:27:33 UTC (rev 51253) @@ -403,6 +403,7 @@ case LCK_bdb: case LCK_rel_exist: case LCK_rel_partners: + case LCK_rel_rescan: case LCK_idx_exist: case LCK_shadow: case LCK_retaining: Modified: firebird/trunk/src/jrd/lck.h =================================================================== --- firebird/trunk/src/jrd/lck.h 2010-06-15 12:00:00 UTC (rev 51252) +++ firebird/trunk/src/jrd/lck.h 2010-06-15 12:27:33 UTC (rev 51253) @@ -56,7 +56,8 @@ LCK_cancel, // Cancellation lock LCK_btr_dont_gc, // Prevent removal of b-tree page from index LCK_shared_counter, // Database-wide shared counter - LCK_fun_exist // Function existence lock + LCK_fun_exist, // Function existence lock + LCK_rel_rescan // Relation forced rescan lock }; // Lock owner types Modified: firebird/trunk/src/jrd/met.epp =================================================================== --- firebird/trunk/src/jrd/met.epp 2010-06-15 12:00:00 UTC (rev 51252) +++ firebird/trunk/src/jrd/met.epp 2010-06-15 12:27:33 UTC (rev 51253) @@ -112,6 +112,7 @@ static int blocking_ast_procedure(void*); static int blocking_ast_relation(void*); static int partners_ast_relation(void*); +static int rescan_ast_relation(void*); static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, trig_vec**, const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&, const bid*); static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*); @@ -2515,6 +2516,7 @@ { LCK_release(tdbb, check_relation->rel_existence_lock); LCK_release(tdbb, check_relation->rel_partners_lock); + LCK_release(tdbb, check_relation->rel_rescan_lock); check_relation->rel_flags &= ~REL_check_partners; check_relation->rel_flags |= REL_deleted; } @@ -2597,6 +2599,7 @@ { LCK_release(tdbb, check_relation->rel_existence_lock); LCK_release(tdbb, check_relation->rel_partners_lock); + LCK_release(tdbb, check_relation->rel_rescan_lock); check_relation->rel_flags &= ~REL_check_partners; check_relation->rel_flags |= REL_deleted; } @@ -3203,6 +3206,19 @@ lock->lck_ast = partners_ast_relation; } + { // Scope block. + Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock; + relation->rel_rescan_lock = lock; + lock->lck_parent = dbb->dbb_lock; + lock->lck_dbb = dbb; + lock->lck_key.lck_long = relation->rel_id; + lock->lck_length = sizeof(lock->lck_key.lck_long); + lock->lck_type = LCK_rel_rescan; + lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type); + lock->lck_object = relation; + lock->lck_ast = rescan_ast_relation; + } + // This should check system flag instead. if (relation->rel_id <= max_sys_rel) { return relation; @@ -3814,6 +3830,7 @@ MET_release_triggers(tdbb, &tmp_vector); } + LCK_lock(tdbb, relation->rel_rescan_lock, LCK_SR, LCK_WAIT); relation->rel_flags &= ~REL_being_scanned; relation->rel_current_format = NULL; @@ -4125,6 +4142,32 @@ } +static int rescan_ast_relation(void* ast_object) +{ + jrd_rel* relation = static_cast<jrd_rel*>(ast_object); + + try + { + Database* dbb = relation->rel_rescan_lock->lck_dbb; + + Database::SyncGuard dsGuard(dbb, true); + + ThreadContextHolder tdbb; + tdbb->setDatabase(dbb); + tdbb->setAttachment(relation->rel_rescan_lock->lck_attachment); + + Jrd::ContextPoolHolder context(tdbb, 0); + + LCK_release(tdbb, relation->rel_rescan_lock); + relation->rel_flags &= ~REL_scanned; + } + catch (const Firebird::Exception&) + {} // no-op + + return 0; +} + + static void get_trigger(thread_db* tdbb, jrd_rel* relation, bid* blob_id, bid* debug_blob_id, trig_vec** ptr, const TEXT* name, FB_UINT64 type, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-06-18 12:49:37
|
Revision: 51269 http://firebird.svn.sourceforge.net/firebird/?rev=51269&view=rev Author: asfernandes Date: 2010-06-18 12:49:31 +0000 (Fri, 18 Jun 2010) Log Message: ----------- Fixed CORE-3056 - Problems may happen when issuing DDL commands in the same transaction after CREATE COLLATION was issued Modified Paths: -------------- firebird/trunk/src/jrd/dfw.epp firebird/trunk/src/jrd/drq.h firebird/trunk/src/jrd/dyn_def.epp firebird/trunk/src/jrd/irq.h Modified: firebird/trunk/src/jrd/dfw.epp =================================================================== --- firebird/trunk/src/jrd/dfw.epp 2010-06-18 12:41:59 UTC (rev 51268) +++ firebird/trunk/src/jrd/dfw.epp 2010-06-18 12:49:31 UTC (rev 51269) @@ -2974,47 +2974,10 @@ WITH COLL.RDB$COLLATION_NAME EQ work->dfw_name.c_str() AND COLL.RDB$CHARACTER_SET_ID EQ charSetId { - if (COLL.RDB$COLLATION_ID.NULL) + if (COLL.RDB$SYSTEM_FLAG != 0) { - // ASF: User collations are created with the last number available, - // to minimize the possibility of conflicts with future system collations. - // The greater available number is 126 to avoid signed/unsigned problems. - - SSHORT id = 126; - - AutoCacheRequest request(tdbb, irq_l_colls, IRQ_REQUESTS); - - FOR(REQUEST_HANDLE request) - Y IN RDB$COLLATIONS - WITH Y.RDB$CHARACTER_SET_ID = COLL.RDB$CHARACTER_SET_ID - SORTED BY DESCENDING Y.RDB$COLLATION_ID - { - if (!COLL.RDB$COLLATION_ID.NULL) - break; - - if (Y.RDB$COLLATION_ID + 1 <= id) - COLL.RDB$COLLATION_ID.NULL = FALSE; - else - id = Y.RDB$COLLATION_ID - 1; - } - END_FOR - - if (COLL.RDB$COLLATION_ID.NULL) - { - ERR_post(Arg::Gds(isc_no_meta_update) << - Arg::Gds(isc_max_coll_per_charset)); - } - else - { - MODIFY COLL USING - COLL.RDB$COLLATION_ID = id; - END_MODIFY - } - } - else - { SLONG length = 0; - Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> buffer; + HalfStaticArray<UCHAR, BUFFER_SMALL> buffer; if (!COLL.RDB$SPECIFIC_ATTRIBUTES.NULL) { @@ -3023,8 +2986,8 @@ length = BLB_get_data(tdbb, blob, buffer.getBuffer(length), length); } - const Firebird::string specificAttributes((const char*) buffer.begin(), length); - Firebird::string newSpecificAttributes; + const string specificAttributes((const char*) buffer.begin(), length); + string newSpecificAttributes; // ASF: If setupCollationAttributes fail we store the original // attributes. This should be what we want for new databases @@ -3042,12 +3005,8 @@ else { COLL.RDB$SPECIFIC_ATTRIBUTES.NULL = FALSE; - - blb* blob = BLB_create(tdbb, transaction, &COLL.RDB$SPECIFIC_ATTRIBUTES); - BLB_put_segment(tdbb, blob, - (const UCHAR*) newSpecificAttributes.begin(), - newSpecificAttributes.length()); - BLB_close(tdbb, blob); + attachment->storeMetaDataBlob(tdbb, transaction, + &COLL.RDB$SPECIFIC_ATTRIBUTES, newSpecificAttributes); } END_MODIFY } Modified: firebird/trunk/src/jrd/drq.h =================================================================== --- firebird/trunk/src/jrd/drq.h 2010-06-18 12:41:59 UTC (rev 51268) +++ firebird/trunk/src/jrd/drq.h 2010-06-18 12:49:31 UTC (rev 51269) @@ -231,6 +231,7 @@ drq_e_ident_gens, // erase generators (identity column) drq_l_ident_gens, // lookup generators (identity column) drq_m_prm_view, // modify view's field source inherited from parameters + drq_l_max_coll_id, // lookup max collation id drq_MAX }; Modified: firebird/trunk/src/jrd/dyn_def.epp =================================================================== --- firebird/trunk/src/jrd/dyn_def.epp 2010-06-18 12:41:59 UTC (rev 51268) +++ firebird/trunk/src/jrd/dyn_def.epp 2010-06-18 12:49:31 UTC (rev 51269) @@ -122,9 +122,10 @@ **************************************/ thread_db* tdbb = JRD_get_thread_data(); + Jrd::Attachment* attachment = tdbb->getAttachment(); - Firebird::MetaName collation_name; - Firebird::MetaName charsetName; + MetaName collation_name; + MetaName charsetName; GET_STRING(ptr, collation_name); @@ -145,7 +146,7 @@ USHORT attributes_on = 0; USHORT attributes_off = 0; SSHORT specific_attributes_charset = CS_NONE; - Firebird::UCharBuffer specific_attributes; + UCharBuffer specific_attributes; X.RDB$SYSTEM_FLAG = 0; X.RDB$SYSTEM_FLAG.NULL = FALSE; @@ -186,7 +187,7 @@ { if (info.specificAttributes.getCount() != 0) { - Firebird::UCharBuffer temp; + UCharBuffer temp; ULONG size = info.specificAttributes.getCount() * cs->maxBytesPerChar(); size = INTL_convert_bytes(tdbb, X.RDB$CHARACTER_SET_ID, @@ -243,7 +244,7 @@ { if (specific_attributes.getCount() != 0) { - Firebird::UCharBuffer temp; + UCharBuffer temp; ULONG size = specific_attributes.getCount() * cs->maxBytesPerChar(); size = INTL_convert_bytes(tdbb, X.RDB$CHARACTER_SET_ID, @@ -283,19 +284,19 @@ fb_assert(cs); if (cs) { - Firebird::IntlUtil::SpecificAttributesMap map; + IntlUtil::SpecificAttributesMap map; - if (!Firebird::IntlUtil::parseSpecificAttributes( + if (!IntlUtil::parseSpecificAttributes( cs, info.specificAttributes.getCount(), info.specificAttributes.begin(), &map) || - !Firebird::IntlUtil::parseSpecificAttributes( + !IntlUtil::parseSpecificAttributes( cs, specific_attributes.getCount(), specific_attributes.begin(), &map)) { DYN_error_punt(false, 222); // msg: 222: "Invalid collation attributes" } - const Firebird::string s = Firebird::IntlUtil::generateSpecificAttributes(cs, map); - Firebird::string newSpecificAttributes; + const string s = IntlUtil::generateSpecificAttributes(cs, map); + string newSpecificAttributes; if (!IntlManager::setupCollationAttributes( info.baseCollationName.c_str(), info.charsetName.c_str(), s, @@ -337,11 +338,42 @@ // msg: 222: "Invalid collation attributes" } + // ASF: User collations are created with the last number available, + // to minimize the possibility of conflicts with future system collations. + // The greater available number is 126 to avoid signed/unsigned problems. + + X.RDB$COLLATION_ID.NULL = TRUE; + X.RDB$COLLATION_ID = 126; + + AutoCacheRequest request2(tdbb, drq_l_max_coll_id, DYN_REQUESTS); + + FOR(REQUEST_HANDLE request2) + Y IN RDB$COLLATIONS + WITH Y.RDB$CHARACTER_SET_ID = X.RDB$CHARACTER_SET_ID AND + Y.RDB$COLLATION_ID NOT MISSING + SORTED BY DESCENDING Y.RDB$COLLATION_ID + { + if (Y.RDB$COLLATION_ID + 1 <= X.RDB$COLLATION_ID) + { + X.RDB$COLLATION_ID.NULL = FALSE; + break; + } + else + X.RDB$COLLATION_ID = Y.RDB$COLLATION_ID - 1; + } + END_FOR + + if (X.RDB$COLLATION_ID.NULL) + { + ERR_post(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_max_coll_per_charset)); + } + b_ending_store = true; } END_STORE } - catch (const Firebird::Exception& ex) + catch (const Exception& ex) { Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); if (b_ending_store) Modified: firebird/trunk/src/jrd/irq.h =================================================================== --- firebird/trunk/src/jrd/irq.h 2010-06-18 12:41:59 UTC (rev 51268) +++ firebird/trunk/src/jrd/irq.h 2010-06-18 12:49:31 UTC (rev 51269) @@ -122,7 +122,6 @@ irq_m_fields7, // process a modification of RDB$FIELDS for functions irq_m_fields8, // process a modification of RDB$FIELDS for functions (TYPE OF COLUMN) irq_m_fields9, // process a modification of RDB$FIELDS for packaged functions (TYPE OF COLUMN) - irq_l_colls, // lookup collations irq_l_relfield, // lookup a relation field irq_verify_trusted_role, // ensure trusted role exists This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-05 00:45:04
|
Revision: 51395 http://firebird.svn.sourceforge.net/firebird/?rev=51395&view=rev Author: asfernandes Date: 2010-08-05 00:44:58 +0000 (Thu, 05 Aug 2010) Log Message: ----------- Fix DDL triggers Modified Paths: -------------- firebird/trunk/src/jrd/SysFunction.cpp firebird/trunk/src/jrd/exe.cpp Modified: firebird/trunk/src/jrd/SysFunction.cpp =================================================================== --- firebird/trunk/src/jrd/SysFunction.cpp 2010-08-04 15:50:26 UTC (rev 51394) +++ firebird/trunk/src/jrd/SysFunction.cpp 2010-08-05 00:44:58 UTC (rev 51395) @@ -2143,7 +2143,8 @@ BLB_close(tdbb, blob); dsc result; - result.makeBlob(isc_blob_text, ttype_dynamic, (ISC_QUAD*) &impure->vlu_misc.vlu_bid); + result.makeBlob(isc_blob_text, attachment->att_charset, + (ISC_QUAD*) &impure->vlu_misc.vlu_bid); EVL_make_value(tdbb, &result, impure); request->req_flags &= ~req_null; Modified: firebird/trunk/src/jrd/exe.cpp =================================================================== --- firebird/trunk/src/jrd/exe.cpp 2010-08-04 15:50:26 UTC (rev 51394) +++ firebird/trunk/src/jrd/exe.cpp 2010-08-05 00:44:58 UTC (rev 51395) @@ -1695,8 +1695,10 @@ { jrd_req* trigger = ptr->statement->findRequest(tdbb); trigger->req_rpb[0].rpb_record = old_rec ? old_rec : null_rec; - trigger->req_rpb[1].rpb_record = new_rec ? new_rec : null_rec; + if (trigger->req_rpb.getCount() > 1) + trigger->req_rpb[1].rpb_record = new_rec ? new_rec : null_rec; + if (old_rec && trigger_action != jrd_req::req_trigger_insert) { trigger->req_rpb[0].rpb_number = old_rpb->rpb_number; @@ -1713,7 +1715,7 @@ trigger->req_rpb[1].rpb_number = new_rpb->rpb_number; trigger->req_rpb[1].rpb_number.setValid(true); } - else + else if (trigger->req_rpb.getCount() > 1) trigger->req_rpb[1].rpb_number.setValid(false); trigger->req_timestamp = timestamp; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-07 02:44:45
|
Revision: 51407 http://firebird.svn.sourceforge.net/firebird/?rev=51407&view=rev Author: asfernandes Date: 2010-08-07 02:44:39 +0000 (Sat, 07 Aug 2010) Log Message: ----------- Misc Modified Paths: -------------- firebird/trunk/src/jrd/dyn.epp firebird/trunk/src/jrd/dyn_def.epp firebird/trunk/src/jrd/dyn_df_proto.h Modified: firebird/trunk/src/jrd/dyn.epp =================================================================== --- firebird/trunk/src/jrd/dyn.epp 2010-08-07 02:43:29 UTC (rev 51406) +++ firebird/trunk/src/jrd/dyn.epp 2010-08-07 02:44:39 UTC (rev 51407) @@ -419,7 +419,7 @@ break; case isc_dyn_def_idx: - DYN_define_index(gbl, ptr, relation_name, verb); + DYN_define_index(gbl, ptr, relation_name); break; case isc_dyn_mod_idx: Modified: firebird/trunk/src/jrd/dyn_def.epp =================================================================== --- firebird/trunk/src/jrd/dyn_def.epp 2010-08-07 02:43:29 UTC (rev 51406) +++ firebird/trunk/src/jrd/dyn_def.epp 2010-08-07 02:44:39 UTC (rev 51407) @@ -575,8 +575,7 @@ } -void DYN_define_index(Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation_name, - UCHAR index_type) +void DYN_define_index(Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation_name) { /************************************** * @@ -589,6 +588,7 @@ * **************************************/ thread_db* tdbb = JRD_get_thread_data(); + const UCHAR index_type = isc_dyn_def_idx; Firebird::MetaName index_name; UCHAR verb; Firebird::MetaName trigger_name; Modified: firebird/trunk/src/jrd/dyn_df_proto.h =================================================================== --- firebird/trunk/src/jrd/dyn_df_proto.h 2010-08-07 02:43:29 UTC (rev 51406) +++ firebird/trunk/src/jrd/dyn_df_proto.h 2010-08-07 02:44:39 UTC (rev 51407) @@ -28,7 +28,7 @@ void DYN_define_filter(Jrd::Global*, const UCHAR**); void DYN_define_function(Jrd::Global*, const UCHAR**); void DYN_define_function_arg(Jrd::Global*, const UCHAR**, Firebird::MetaName*); -void DYN_define_index(Jrd::Global*, const UCHAR**, const Firebird::MetaName*, UCHAR); +void DYN_define_index(Jrd::Global*, const UCHAR**, const Firebird::MetaName*); void DYN_define_role(Jrd::Global*, const UCHAR**); void DYN_define_shadow(Jrd::Global*, const UCHAR**); void DYN_define_difference(Jrd::Global*, const UCHAR**); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2010-08-12 10:32:57
|
Revision: 51439 http://firebird.svn.sourceforge.net/firebird/?rev=51439&view=rev Author: robocop Date: 2010-08-12 10:32:50 +0000 (Thu, 12 Aug 2010) Log Message: ----------- Misc. Modified Paths: -------------- firebird/trunk/src/jrd/exe.h firebird/trunk/src/jrd/par.cpp Modified: firebird/trunk/src/jrd/exe.h =================================================================== --- firebird/trunk/src/jrd/exe.h 2010-08-12 03:16:45 UTC (rev 51438) +++ firebird/trunk/src/jrd/exe.h 2010-08-12 10:32:50 UTC (rev 51439) @@ -766,7 +766,7 @@ public: struct Dependency { - Dependency(int aObjType) + explicit Dependency(int aObjType) { memset(this, 0, sizeof(*this)); objType = aObjType; Modified: firebird/trunk/src/jrd/par.cpp =================================================================== --- firebird/trunk/src/jrd/par.cpp 2010-08-12 03:16:45 UTC (rev 51438) +++ firebird/trunk/src/jrd/par.cpp 2010-08-12 10:32:50 UTC (rev 51439) @@ -1128,7 +1128,7 @@ // Fake RecordSelExpr forNode->rse = PAR_make_node(tdbb, 1 + rse_delta + 2); - RecordSelExpr* rse = (RecordSelExpr*)(jrd_nod*) forNode->rse; + RecordSelExpr* rse = reinterpret_cast<RecordSelExpr*>(static_cast<jrd_nod*>(forNode->rse)); rse->nod_type = nod_rse; rse->nod_count = 0; rse->rse_count = 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-25 00:42:23
|
Revision: 51470 http://firebird.svn.sourceforge.net/firebird/?rev=51470&view=rev Author: asfernandes Date: 2010-08-25 00:42:17 +0000 (Wed, 25 Aug 2010) Log Message: ----------- Misc Modified Paths: -------------- firebird/trunk/src/jrd/cmp.cpp firebird/trunk/src/jrd/met.epp Modified: firebird/trunk/src/jrd/cmp.cpp =================================================================== --- firebird/trunk/src/jrd/cmp.cpp 2010-08-24 17:49:23 UTC (rev 51469) +++ firebird/trunk/src/jrd/cmp.cpp 2010-08-25 00:42:17 UTC (rev 51470) @@ -2557,7 +2557,10 @@ node->rseNode->flags |= RseNode::FLAG_VARIANT; } else + { + fb_assert(node->legacyNode->nod_type != nod_class_recsrcnode_jrd); node->legacyNode->nod_flags &= ~nod_invariant; + } } } Modified: firebird/trunk/src/jrd/met.epp =================================================================== --- firebird/trunk/src/jrd/met.epp 2010-08-24 17:49:23 UTC (rev 51469) +++ firebird/trunk/src/jrd/met.epp 2010-08-25 00:42:17 UTC (rev 51470) @@ -4374,9 +4374,7 @@ blr.add(blr_not_nullable); if (parameter->prm_mechanism == prm_mech_type_of) - { PreparedStatement::generateBlr(¶meter->prm_desc, blr); - } else { fb_assert(parameter->prm_mechanism == prm_mech_normal); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-25 01:35:43
|
Revision: 51472 http://firebird.svn.sourceforge.net/firebird/?rev=51472&view=rev Author: asfernandes Date: 2010-08-25 01:35:33 +0000 (Wed, 25 Aug 2010) Log Message: ----------- Misc Modified Paths: -------------- firebird/trunk/src/jrd/RecordSourceNodes.cpp firebird/trunk/src/jrd/RecordSourceNodes.h firebird/trunk/src/jrd/opt.cpp Modified: firebird/trunk/src/jrd/RecordSourceNodes.cpp =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-08-25 01:01:22 UTC (rev 51471) +++ firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-08-25 01:35:33 UTC (rev 51472) @@ -41,11 +41,11 @@ static SSHORT strcmpSpace(const char* p, const char* q); static void processSource(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, RecordSourceNode* source, jrd_nod** boolean, RecordSourceNodeStack& stack); -static void processMap(thread_db* tdbb, CompilerScratch* csb, jrd_nod* map, Format** input_format); +static void processMap(thread_db* tdbb, CompilerScratch* csb, jrd_nod* map, Format** inputFormat); static void genDeliverUnmapped(thread_db* tdbb, NodeStack* deliverStack, jrd_nod* map, NodeStack* parentStack, UCHAR shellStream); -static void markIndices(CompilerScratch::csb_repeat* csb_tail, SSHORT relation_id); -static void sortIndicesBySelectivity(CompilerScratch::csb_repeat* csb_tail); +static void markIndices(CompilerScratch::csb_repeat* csbTail, SSHORT relationId); +static void sortIndicesBySelectivity(CompilerScratch::csb_repeat* csbTail); //-------------------- @@ -63,7 +63,7 @@ *tdbb->getDefaultPool()); // Find relation either by id or by name - string* alias_string = NULL; + string* aliasString = NULL; MetaName name; switch (blrOp) @@ -75,8 +75,8 @@ if (blrOp == blr_rid2) { - alias_string = FB_NEW(csb->csb_pool) string(csb->csb_pool); - PAR_name(csb, *alias_string); + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); } if (!(node->relation = MET_lookup_relation_id(tdbb, id, false))) @@ -92,8 +92,8 @@ if (blrOp == blr_relation2) { - alias_string = FB_NEW(csb->csb_pool) string(csb->csb_pool); - PAR_name(csb, *alias_string); + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); } node->relation = MET_lookup_relation(tdbb, name); @@ -109,8 +109,8 @@ // if an alias was passed, store with the relation - if (alias_string) - node->alias = stringDup(*tdbb->getDefaultPool(), *alias_string); + if (aliasString) + node->alias = stringDup(*tdbb->getDefaultPool(), *aliasString); // Scan the relation if it hasn't already been scanned for meta data @@ -131,13 +131,13 @@ fb_assert(node->stream <= MAX_STREAMS); csb->csb_rpt[node->stream].csb_relation = node->relation; - csb->csb_rpt[node->stream].csb_alias = alias_string; + csb->csb_rpt[node->stream].csb_alias = aliasString; if (csb->csb_g_flags & csb_get_dependencies) PAR_dependency(tdbb, csb, node->stream, (SSHORT) -1, ""); } else - delete alias_string; + delete aliasString; return node; } @@ -154,7 +154,7 @@ // Get that stream number so that the flags can be copied // into the newly created child stream. - const int relative_stream = stream ? copier.remap[stream - 1] : stream; + const int relativeStream = stream ? copier.remap[stream - 1] : stream; newSource->stream = copier.csb->nextStream(); copier.remap[stream] = (UCHAR) newSource->stream; @@ -198,12 +198,12 @@ tagged with whatever flags X possesed leading to various errors. - We now store the proper stream no in relative_stream and + We now store the proper stream no in relativeStream and later use it to copy the flags. -Sudesh (03/05/99) **/ copier.csb->csb_rpt[newSource->stream].csb_flags |= - copier.csb->csb_rpt[relative_stream].csb_flags & csb_no_dbkey; + copier.csb->csb_rpt[relativeStream].csb_flags & csb_no_dbkey; return newSource; } @@ -231,23 +231,23 @@ // prepare to check protection of relation when a field in the stream of the // relation is accessed. - jrd_rel* const parent_view = csb->csb_view; - const USHORT view_stream = csb->csb_view_stream; + jrd_rel* const parentView = csb->csb_view; + const USHORT viewStream = csb->csb_view_stream; jrd_rel* relationView = relation; CMP_post_resource(&csb->csb_resources, relationView, Resource::rsc_relation, relationView->rel_id); - view = parent_view; + view = parentView; CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream); - element->csb_view = parent_view; - fb_assert(view_stream <= MAX_STREAMS); - element->csb_view_stream = (UCHAR) view_stream; + element->csb_view = parentView; + fb_assert(viewStream <= MAX_STREAMS); + element->csb_view_stream = (UCHAR) viewStream; // in the case where there is a parent view, find the context name - if (parent_view) + if (parentView) { - const ViewContexts& ctx = parent_view->rel_view_contexts; + const ViewContexts& ctx = parentView->rel_view_contexts; const USHORT key = context; size_t pos; @@ -260,8 +260,8 @@ // check for a view - if not, nothing more to do - RseNode* view_rse = relationView->rel_view_rse; - if (!view_rse) + RseNode* viewRse = relationView->rel_view_rse; + if (!viewRse) return; // we've got a view, expand it @@ -279,12 +279,12 @@ // 1) If the view has a projection, sort, first/skip or explicit plan. // 2) If it's part of an outer join. - if (rse->rse_jointype || // view_rse->rse_jointype || ??? - view_rse->rse_sorted || view_rse->rse_projection || view_rse->rse_first || - view_rse->rse_skip || view_rse->rse_plan) + if (rse->rse_jointype || // viewRse->rse_jointype || ??? + viewRse->rse_sorted || viewRse->rse_projection || viewRse->rse_first || + viewRse->rse_skip || viewRse->rse_plan) { NodeCopier copier(csb, map); - RseNode* copy = view_rse->copy(tdbb, copier); + RseNode* copy = viewRse->copy(tdbb, copier); DEBUG; copy->pass1(tdbb, csb, csb->csb_view); stack.push(copy); @@ -298,13 +298,13 @@ // projection will be copied and correctly mapped later, but we don't have all // the base streams yet - if (view_rse->rse_projection) - rse->rse_projection = view_rse->rse_projection; + if (viewRse->rse_projection) + rse->rse_projection = viewRse->rse_projection; // disect view into component relations - NestConst<RecordSourceNode>* arg = view_rse->rse_relations.begin(); - for (const NestConst<RecordSourceNode>* const end = view_rse->rse_relations.end(); arg != end; ++arg) + NestConst<RecordSourceNode>* arg = viewRse->rse_relations.begin(); + for (const NestConst<RecordSourceNode>* const end = viewRse->rse_relations.end(); arg != end; ++arg) { // this call not only copies the node, it adds any streams it finds to the map NodeCopier copier(csb, map); @@ -323,19 +323,19 @@ // base table(s) instead of the view's context (see bug #8822), so we are ready to context- // recognize them in CMP_pass1() - that is, replace the field nodes with actual field blocks. - if (view_rse->rse_projection) + if (viewRse->rse_projection) { rse->rse_projection = - CMP_pass1(tdbb, csb, NodeCopier::copy(tdbb, csb, view_rse->rse_projection, map)); + CMP_pass1(tdbb, csb, NodeCopier::copy(tdbb, csb, viewRse->rse_projection, map)); } // if we encounter a boolean, copy it and retain it by ANDing it in with the // boolean on the parent view, if any - if (view_rse->rse_boolean) + if (viewRse->rse_boolean) { jrd_nod* node = CMP_pass1(tdbb, csb, NodeCopier::copy(tdbb, - csb, view_rse->rse_boolean, map)); + csb, viewRse->rse_boolean, map)); if (*boolean) { @@ -363,9 +363,9 @@ } RecordSource* RelationSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) { fb_assert(stream <= MAX_UCHAR); @@ -392,14 +392,12 @@ // if we have seen any booleans or sort fields, we may be able to // use an index to optimize them; retrieve the current format of // all indices at this time so we can determine if it's possible - // AB: if a parent_stack was available and conjunct_count was 0 + // AB: if a parentStack was available and conjunctCount was 0 // then no indices where retrieved. Added also OR check on - // parent_stack below. SF BUG # [ 508594 ] + // parentStack below. SF BUG # [ 508594 ] - if (conjunct_count || sort || aggregate || parent_stack) + if (conjunctCount || sort || aggregate || parentStack) { - jrd_rel* relation = (jrd_rel*) this->relation; - if (relation && !relation->rel_file && !relation->isVirtual()) { csb->csb_rpt[stream].csb_indices = @@ -428,7 +426,7 @@ SET_TDBB(tdbb); jrd_prc* procedure = NULL; - string* alias_string = NULL; + string* aliasString = NULL; QualifiedName name; switch (blrOp) @@ -440,8 +438,8 @@ if (blrOp == blr_pid2) { - alias_string = FB_NEW(csb->csb_pool) string(csb->csb_pool); - PAR_name(csb, *alias_string); + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); } if (!(procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0))) @@ -462,8 +460,8 @@ if (blrOp == blr_procedure2 || blrOp == blr_procedure4) { - alias_string = FB_NEW(csb->csb_pool) string(csb->csb_pool); - PAR_name(csb, *alias_string); + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); } procedure = MET_lookup_procedure(tdbb, name, false); @@ -495,7 +493,7 @@ node->stream = PAR_context(csb, &node->context); csb->csb_rpt[node->stream].csb_procedure = procedure; - csb->csb_rpt[node->stream].csb_alias = alias_string; + csb->csb_rpt[node->stream].csb_alias = aliasString; PAR_procedure_parms(tdbb, csb, procedure, node->in_msg.getAddress(), node->inputs.getAddress(), true); @@ -557,20 +555,20 @@ CMP_post_procedure_access(tdbb, csb, proc); CMP_post_resource(&csb->csb_resources, proc, Resource::rsc_procedure, proc->getId()); - jrd_rel* const parent_view = csb->csb_view; - const USHORT view_stream = csb->csb_view_stream; - view = parent_view; + jrd_rel* const parentView = csb->csb_view; + const USHORT viewStream = csb->csb_view_stream; + view = parentView; CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream); - element->csb_view = parent_view; - fb_assert(view_stream <= MAX_STREAMS); - element->csb_view_stream = (UCHAR) view_stream; + element->csb_view = parentView; + fb_assert(viewStream <= MAX_STREAMS); + element->csb_view_stream = (UCHAR) viewStream; // in the case where there is a parent view, find the context name - if (parent_view) + if (parentView) { - const ViewContexts& ctx = parent_view->rel_view_contexts; + const ViewContexts& ctx = parentView->rel_view_contexts; const USHORT key = context; size_t pos; @@ -597,9 +595,9 @@ } RecordSource* ProcedureSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) { fb_assert(stream <= MAX_UCHAR); @@ -610,8 +608,8 @@ beds[++beds[0]] = (UCHAR) stream; RecordSource* rsb = generate(tdbb, opt); - fb_assert(local_streams[0] < MAX_STREAMS && local_streams[0] < MAX_UCHAR); - local_streams[++local_streams[0]] = stream; + fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); + localStreams[++localStreams[0]] = stream; return rsb; } @@ -624,8 +622,8 @@ jrd_prc* const proc = MET_lookup_procedure_id(tdbb, procedure, false, false, 0); CompilerScratch* const csb = opt->opt_csb; - CompilerScratch::csb_repeat* const csb_tail = &csb->csb_rpt[stream]; - const string alias = OPT_make_alias(tdbb, csb, csb_tail); + CompilerScratch::csb_repeat* const csbTail = &csb->csb_rpt[stream]; + const string alias = OPT_make_alias(tdbb, csb, csbTail); return FB_NEW(*tdbb->getDefaultPool()) ProcedureScan(csb, alias, stream, proc, inputs, in_msg); } @@ -768,9 +766,9 @@ } RecordSource* AggregateSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) { fb_assert(stream <= MAX_UCHAR); @@ -780,17 +778,17 @@ beds[++beds[0]] = (UCHAR) stream; - NodeStack::const_iterator stack_end; - if (parent_stack) - stack_end = conjunct_stack.merge(*parent_stack); + NodeStack::const_iterator stackEnd; + if (parentStack) + stackEnd = conjunctStack.merge(*parentStack); - RecordSource* rsb = generate(tdbb, opt, &conjunct_stack, stream); + RecordSource* rsb = generate(tdbb, opt, &conjunctStack, stream); - if (parent_stack) - conjunct_stack.split(stack_end, *parent_stack); + if (parentStack) + conjunctStack.split(stackEnd, *parentStack); - fb_assert(local_streams[0] < MAX_STREAMS && local_streams[0] < MAX_UCHAR); - local_streams[++local_streams[0]] = stream; + fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); + localStreams[++localStreams[0]] = stream; return rsb; } @@ -798,7 +796,7 @@ // Generate an RecordSource (Record Source Block) for each aggregate operation. // Generate an AggregateSort (Aggregate SortedStream Block) for each DISTINCT aggregate. RecordSource* AggregateSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt, - NodeStack* parent_stack, UCHAR shellStream) + NodeStack* parentStack, UCHAR shellStream) { SET_TDBB(tdbb); @@ -810,7 +808,7 @@ // Those fields are mappings. Mappings that hold a plain field may be used // to distribute. Handle the simple cases only. NodeStack deliverStack; - genDeliverUnmapped(tdbb, &deliverStack, map, parent_stack, shellStream); + genDeliverUnmapped(tdbb, &deliverStack, map, parentStack, shellStream); // try to optimize MAX and MIN to use an index; for now, optimize // only the simplest case, although it is probably possible @@ -836,7 +834,7 @@ rse->rse_aggregate = aggregate; } - RecordSource* const next_rsb = OPT_compile(tdbb, csb, rse, &deliverStack); + RecordSource* const nextRsb = OPT_compile(tdbb, csb, rse, &deliverStack); fb_assert(stream <= MAX_STREAMS); fb_assert(stream <= MAX_UCHAR); @@ -844,7 +842,7 @@ // allocate and optimize the record source block AggregatedStream* const rsb = FB_NEW(*tdbb->getDefaultPool()) AggregatedStream(csb, stream, - group, map, next_rsb); + group, map, nextRsb); if (rse->rse_aggregate) { @@ -894,12 +892,12 @@ fb_assert(node->stream <= MAX_STREAMS); // assign separate context for mapped record if union is recursive - USHORT map_stream = node->stream; + USHORT stream2 = node->stream; if (node->recursive) { - map_stream = PAR_context(csb, 0); - node->mapStream = map_stream; + stream2 = PAR_context(csb, 0); + node->mapStream = stream2; } SSHORT count = (unsigned int) csb->csb_blr_reader.getByte(); @@ -909,7 +907,7 @@ while (--count >= 0) { node->clauses.push(RseNode::getFrom(PAR_parse_node(tdbb, csb, TYPE_RSE))); - node->maps.push(parseMap(tdbb, csb, map_stream)); + node->maps.push(parseMap(tdbb, csb, stream2)); } return node; @@ -980,7 +978,7 @@ } } -// Process a union clause of an RseNode. +// Process a union clause of a RseNode. void UnionSourceNode::pass2(thread_db* tdbb, CompilerScratch* csb) { SET_TDBB(tdbb); @@ -1036,40 +1034,40 @@ } RecordSource* UnionSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) { - const SSHORT i = (SSHORT) key_streams[0]; - computeDbKeyStreams(key_streams); + const SSHORT i = (SSHORT) keyStreams[0]; + computeDbKeyStreams(keyStreams); - NodeStack::const_iterator stack_end; - if (parent_stack) - stack_end = conjunct_stack.merge(*parent_stack); + NodeStack::const_iterator stackEnd; + if (parentStack) + stackEnd = conjunctStack.merge(*parentStack); - RecordSource* rsb = generate(tdbb, opt, key_streams + i + 1, - (USHORT) (key_streams[0] - i), &conjunct_stack, stream); + RecordSource* rsb = generate(tdbb, opt, keyStreams + i + 1, + (USHORT) (keyStreams[0] - i), &conjunctStack, stream); - if (parent_stack) - conjunct_stack.split(stack_end, *parent_stack); + if (parentStack) + conjunctStack.split(stackEnd, *parentStack); - fb_assert(local_streams[0] < MAX_STREAMS && local_streams[0] < MAX_UCHAR); - local_streams[++local_streams[0]] = stream; + fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); + localStreams[++localStreams[0]] = stream; return rsb; } // Generate a union complex. RecordSource* UnionSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt, UCHAR* streams, - USHORT nstreams, NodeStack* parent_stack, UCHAR shellStream) + USHORT nstreams, NodeStack* parentStack, UCHAR shellStream) { SET_TDBB(tdbb); CompilerScratch* csb = opt->opt_csb; HalfStaticArray<RecordSource*, OPT_STATIC_ITEMS> rsbs; - const SLONG base_impure = CMP_impure(csb, 0); + const SLONG baseImpure = CMP_impure(csb, 0); NestConst<RseNode>* ptr = clauses.begin(); NestConst<jrd_nod>* ptr2 = maps.begin(); @@ -1084,7 +1082,7 @@ // hvlad: don't do it for recursive unions else they will work wrong ! NodeStack deliverStack; if (!recursive) - genDeliverUnmapped(tdbb, &deliverStack, map, parent_stack, shellStream); + genDeliverUnmapped(tdbb, &deliverStack, map, parentStack, shellStream); rsbs.add(OPT_compile(tdbb, csb, rse, &deliverStack)); @@ -1100,7 +1098,7 @@ // hvlad: save size of inner impure area and context of mapped record // for recursive processing later return FB_NEW(*tdbb->getDefaultPool()) RecursiveStream(csb, stream, mapStream, - rsbs[0], rsbs[1], maps[0], maps[1], nstreams, streams, base_impure); + rsbs[0], rsbs[1], maps[0], maps[1], nstreams, streams, baseImpure); } return FB_NEW(*tdbb->getDefaultPool()) Union(csb, stream, clauses.getCount(), rsbs.begin(), @@ -1173,8 +1171,7 @@ PAR_syntax_error(csb, "blr_partition_by"); SSHORT context; - SSHORT partitionStream; - partitionStream = PAR_context(csb, &context); + SSHORT partitionStream = PAR_context(csb, &context); jrd_nod* list = PAR_make_node(tdbb, e_part_length); list->nod_type = nod_list; @@ -1336,9 +1333,9 @@ } RecordSource* WindowSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) { const jrd_nod* nodWindows = windows; @@ -1365,8 +1362,8 @@ for (StreamsArray::iterator i = rsbStreams.begin(); i != rsbStreams.end(); ++i) { - fb_assert(local_streams[0] < MAX_STREAMS && local_streams[0] < MAX_UCHAR); - local_streams[++local_streams[0]] = *i; + fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); + localStreams[++localStreams[0]] = *i; } return rsb; @@ -1434,19 +1431,19 @@ // yet, mark the RseNode as variant to make sure that statement- // level aggregates are not treated as invariants -- bug #6535 - bool top_level_rse = true; + bool topLevelRse = true; for (LegacyNodeOrRseNode* node = csb->csb_current_nodes.begin(); node != csb->csb_current_nodes.end(); ++node) { if (node->rseNode) { - top_level_rse = false; + topLevelRse = false; break; } } - if (top_level_rse) + if (topLevelRse) flags |= FLAG_VARIANT; csb->csb_current_nodes.push(this); @@ -1514,7 +1511,7 @@ void RseNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, jrd_nod** boolean, RecordSourceNodeStack& stack) { - // in the case of an RseNode, it is possible that a new RseNode will be generated, + // in the case of a RseNode, it is possible that a new RseNode will be generated, // so wait to process the source before we push it on the stack (bug 8039) // The addition of the JOIN syntax for specifying inner joins causes an @@ -1614,9 +1611,9 @@ } RecordSource* RseNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) { // for nodes which are not relations, generate an rsb to @@ -1624,8 +1621,8 @@ // find all the substreams involved and compile them as well computeRseStreams(csb, beds); - computeRseStreams(csb, local_streams); - computeDbKeyStreams(key_streams); + computeRseStreams(csb, localStreams); + computeDbKeyStreams(keyStreams); RecordSource* rsb; @@ -1643,8 +1640,8 @@ csb->csb_rpt[*i].csb_flags |= csb_active; } - //const NodeStack::iterator stackSavepoint(conjunct_stack); - NodeStack::const_iterator stack_end; + //const NodeStack::iterator stackSavepoint(conjunctStack); + NodeStack::const_iterator stackEnd; NodeStack deliverStack; if (rse->rse_jointype != blr_inner) @@ -1655,8 +1652,8 @@ // Note! Don't forget that this can be burried inside a expression // such as "CASE WHEN (FieldX IS NULL) THEN 0 ELSE 1 END = 0" NodeStack::iterator stackItem; - if (parent_stack) - stackItem = *parent_stack; + if (parentStack) + stackItem = *parentStack; for (; stackItem.hasData(); ++stackItem) { @@ -1665,25 +1662,26 @@ if (!PossibleUnknownFinder::find(deliverNode)) deliverStack.push(deliverNode); } - stack_end = conjunct_stack.merge(deliverStack); + + stackEnd = conjunctStack.merge(deliverStack); } else { - if (parent_stack) - stack_end = conjunct_stack.merge(*parent_stack); + if (parentStack) + stackEnd = conjunctStack.merge(*parentStack); } - rsb = OPT_compile(tdbb, csb, this, &conjunct_stack); + rsb = OPT_compile(tdbb, csb, this, &conjunctStack); if (rse->rse_jointype != blr_inner) { // Remove previously added parent conjuctions from the stack. - conjunct_stack.split(stack_end, deliverStack); + conjunctStack.split(stackEnd, deliverStack); } else { - if (parent_stack) - conjunct_stack.split(stack_end, *parent_stack); + if (parentStack) + conjunctStack.split(stackEnd, *parentStack); } if (rse->rse_jointype == blr_left) @@ -1693,12 +1691,12 @@ } } else - rsb = OPT_compile(tdbb, csb, this, parent_stack); + rsb = OPT_compile(tdbb, csb, this, parentStack); return rsb; } -// Identify the streams that make up an RseNode. +// Identify the streams that make up a RseNode. void RseNode::computeRseStreams(const CompilerScratch* csb, UCHAR* streams) const { const NestConst<RecordSourceNode>* ptr = rse_relations.begin(); @@ -1768,9 +1766,9 @@ plan->nod_arg[e_retrieve_relation]->nod_arg[0]); fb_assert(recSource->type == RelationSourceNode::TYPE); - const jrd_rel* view_relation = NULL; - const jrd_rel* plan_relation = (jrd_rel*) recSource->relation; - const char* plan_alias = (const char *) recSource->alias; + const jrd_rel* viewRelation = NULL; + const jrd_rel* planRelation = (jrd_rel*) recSource->relation; + const char* planAlias = (const char *) recSource->alias; // find the tail for the relation specified in the RseNode @@ -1783,7 +1781,7 @@ if (tail->csb_map) { - const TEXT* p = plan_alias; + const TEXT* p = planAlias; // if the user has specified an alias, skip past it to find the alias // for the base table (if multiple aliases are specified) @@ -1799,21 +1797,21 @@ } // loop through potentially a stack of views to find the appropriate base table - UCHAR* map_base; + UCHAR* mapBase; - while ( (map_base = tail->csb_map) ) + while ( (mapBase = tail->csb_map) ) { - map = map_base; + map = mapBase; tail = &csb->csb_rpt[*map]; - view_relation = tail->csb_relation; + viewRelation = tail->csb_relation; // if the plan references the view itself, make sure that // the view is on a single table; if it is, fix up the plan // to point to the base relation - if (view_relation->rel_id == plan_relation->rel_id) + if (viewRelation->rel_id == planRelation->rel_id) { - if (!map_base[2]) + if (!mapBase[2]) { map++; tail = &csb->csb_rpt[*map]; @@ -1821,13 +1819,13 @@ else { // view %s has more than one base relation; use aliases to distinguish - ERR_post(Arg::Gds(isc_view_alias) << Arg::Str(plan_relation->rel_name)); + ERR_post(Arg::Gds(isc_view_alias) << Arg::Str(planRelation->rel_name)); } break; } - view_relation = NULL; + viewRelation = NULL; // if the user didn't specify an alias (or didn't specify one // for this level), check to make sure there is one and only one @@ -1835,26 +1833,29 @@ if (!*p) { - const jrd_rel* duplicate_relation = NULL; - UCHAR* duplicate_map = map_base; + const jrd_rel* duplicateRelation = NULL; + UCHAR* duplicateMap = mapBase; + map = NULL; - for (duplicate_map++; *duplicate_map; duplicate_map++) + + for (duplicateMap++; *duplicateMap; ++duplicateMap) { - CompilerScratch::csb_repeat* duplicate_tail = &csb->csb_rpt[*duplicate_map]; - const jrd_rel* relation = duplicate_tail->csb_relation; - if (relation && relation->rel_id == plan_relation->rel_id) + CompilerScratch::csb_repeat* duplicateTail = &csb->csb_rpt[*duplicateMap]; + const jrd_rel* relation = duplicateTail->csb_relation; + + if (relation && relation->rel_id == planRelation->rel_id) { - if (duplicate_relation) + if (duplicateRelation) { // table %s is referenced twice in view; use an alias to distinguish ERR_post(Arg::Gds(isc_duplicate_base_table) << - Arg::Str(duplicate_relation->rel_name)); + Arg::Str(duplicateRelation->rel_name)); } else { - duplicate_relation = relation; - map = duplicate_map; - tail = duplicate_tail; + duplicateRelation = relation; + map = duplicateMap; + tail = duplicateTail; } } } @@ -1864,7 +1865,7 @@ // look through all the base relations for a match - map = map_base; + map = mapBase; for (map++; *map; map++) { tail = &csb->csb_rpt[*map]; @@ -1897,7 +1898,7 @@ if (!*map) { // table %s is referenced in the plan but not the from list - ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(plan_relation->rel_name)); + ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(planRelation->rel_name)); } } @@ -1906,7 +1907,7 @@ if (!map || !*map) { // table %s is referenced in the plan but not the from list - ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(plan_relation->rel_name)); + ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(planRelation->rel_name)); } recSource->setStream(*map); @@ -1917,13 +1918,13 @@ if (!tail->csb_relation) { // table %s is referenced in the plan but not the from list - ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(plan_relation->rel_name)); + ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(planRelation->rel_name)); } - if ((tail->csb_relation->rel_id != plan_relation->rel_id) && !view_relation) + if ((tail->csb_relation->rel_id != planRelation->rel_id) && !viewRelation) { // table %s is referenced in the plan but not the from list - ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(plan_relation->rel_name)); + ERR_post(Arg::Gds(isc_stream_not_found) << Arg::Str(planRelation->rel_name)); } // check if we already have a plan for this stream @@ -2082,7 +2083,7 @@ return (*p > *q) ? 1 : -1; } -// Process a single record source stream from an RseNode. +// Process a single record source stream from a RseNode. // Obviously, if the source is a view, there is more work to do. static void processSource(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, RecordSourceNode* source, jrd_nod** boolean, RecordSourceNodeStack& stack) @@ -2098,13 +2099,13 @@ } // Translate a map block into a format. If the format is missing or incomplete, extend it. -static void processMap(thread_db* tdbb, CompilerScratch* csb, jrd_nod* map, Format** input_format) +static void processMap(thread_db* tdbb, CompilerScratch* csb, jrd_nod* map, Format** inputFormat) { SET_TDBB(tdbb); - Format* format = *input_format; + Format* format = *inputFormat; if (!format) - format = *input_format = Format::newFormat(*tdbb->getDefaultPool(), map->nod_count); + format = *inputFormat = Format::newFormat(*tdbb->getDefaultPool(), map->nod_count); // process alternating rse and map blocks dsc desc2; @@ -2237,8 +2238,9 @@ for (indexArg = 0; (indexArg < boolean->nod_count) && !mappingFound; indexArg++) { jrd_nod* booleanNode = boolean->nod_arg[indexArg]; - if ((booleanNode->nod_type == nod_field) && - ((USHORT)(IPTR) booleanNode->nod_arg[e_fld_stream] == shellStream)) + + if (booleanNode->nod_type == nod_field && + (USHORT)(IPTR) booleanNode->nod_arg[e_fld_stream] == shellStream) { mappingFound = true; } @@ -2274,9 +2276,9 @@ } // Mark indices that were not included in the user-specified access plan. -static void markIndices(CompilerScratch::csb_repeat* csb_tail, SSHORT relation_id) +static void markIndices(CompilerScratch::csb_repeat* csbTail, SSHORT relationId) { - const jrd_nod* plan = csb_tail->csb_plan; + const jrd_nod* plan = csbTail->csb_plan; if (!plan) return; @@ -2285,28 +2287,28 @@ // find out how many indices were specified; if // there were none, this is a sequential retrieval - USHORT plan_count = 0; - const jrd_nod* access_type = plan->nod_arg[e_retrieve_access_type]; + USHORT planCount = 0; + const jrd_nod* accessType = plan->nod_arg[e_retrieve_access_type]; - if (access_type) - plan_count = access_type->nod_count; + if (accessType) + planCount = accessType->nod_count; // go through each of the indices and mark it unusable // for indexed retrieval unless it was specifically mentioned // in the plan; also mark indices for navigational access - index_desc* idx = csb_tail->csb_idx->items; + index_desc* idx = csbTail->csb_idx->items; - for (USHORT i = 0; i < csb_tail->csb_indices; i++) + for (USHORT i = 0; i < csbTail->csb_indices; i++) { - if (access_type) + if (accessType) { - const jrd_nod* const* arg = access_type->nod_arg; - const jrd_nod* const* const end = arg + plan_count; + const jrd_nod* const* arg = accessType->nod_arg; + const jrd_nod* const* const end = arg + planCount; for (; arg < end; arg += e_access_type_length) { - if (relation_id != (SSHORT)(IPTR) arg[e_access_type_relation]) + if (relationId != (SSHORT)(IPTR) arg[e_access_type_relation]) { // index %s cannot be used in the specified plan const char* iname = reinterpret_cast<const char*>(arg[e_access_type_index_name]); @@ -2315,7 +2317,7 @@ if (idx->idx_id == (USHORT)(IPTR) arg[e_access_type_index]) { - if (access_type->nod_type == nod_navigational && arg == access_type->nod_arg) + if (accessType->nod_type == nod_navigational && arg == accessType->nod_arg) { // dimitr: navigational access can use only one index, // hence the extra check added (see the line above) @@ -2340,55 +2342,55 @@ } // Sort SortedStream indices based on there selectivity. Lowest selectivy as first, highest as last. -static void sortIndicesBySelectivity(CompilerScratch::csb_repeat* csb_tail) +static void sortIndicesBySelectivity(CompilerScratch::csb_repeat* csbTail) { - if (csb_tail->csb_plan) + if (csbTail->csb_plan) return; - index_desc* selected_idx = NULL; - Array<index_desc> idx_sort(csb_tail->csb_indices); - bool same_selectivity = false; + index_desc* selectedIdx = NULL; + Array<index_desc> idxSort(csbTail->csb_indices); + bool sameSelectivity = false; - // Walk through the indices and sort them into into idx_sort - // where idx_sort[0] contains the lowest selectivity (best) and - // idx_sort[csb_tail->csb_indices - 1] the highest (worst) + // Walk through the indices and sort them into into idxSort + // where idxSort[0] contains the lowest selectivity (best) and + // idxSort[csbTail->csb_indices - 1] the highest (worst) - if (csb_tail->csb_idx && (csb_tail->csb_indices > 1)) + if (csbTail->csb_idx && (csbTail->csb_indices > 1)) { - for (USHORT j = 0; j < csb_tail->csb_indices; j++) + for (USHORT j = 0; j < csbTail->csb_indices; j++) { float selectivity = 1; // Maximum selectivity is 1 (when all keys are the same) - index_desc* idx = csb_tail->csb_idx->items; + index_desc* idx = csbTail->csb_idx->items; - for (USHORT i = 0; i < csb_tail->csb_indices; i++) + for (USHORT i = 0; i < csbTail->csb_indices; i++) { // Prefer ASC indices in the case of almost the same selectivities if (selectivity > idx->idx_selectivity) - same_selectivity = ((selectivity - idx->idx_selectivity) <= 0.00001); + sameSelectivity = ((selectivity - idx->idx_selectivity) <= 0.00001); else - same_selectivity = ((idx->idx_selectivity - selectivity) <= 0.00001); + sameSelectivity = ((idx->idx_selectivity - selectivity) <= 0.00001); if (!(idx->idx_runtime_flags & idx_marker) && (idx->idx_selectivity <= selectivity) && - !((idx->idx_flags & idx_descending) && same_selectivity)) + !((idx->idx_flags & idx_descending) && sameSelectivity)) { selectivity = idx->idx_selectivity; - selected_idx = idx; + selectedIdx = idx; } ++idx; } // If no index was found than pick the first one available out of the list - if ((!selected_idx) || (selected_idx->idx_runtime_flags & idx_marker)) + if ((!selectedIdx) || (selectedIdx->idx_runtime_flags & idx_marker)) { - idx = csb_tail->csb_idx->items; + idx = csbTail->csb_idx->items; - for (USHORT i = 0; i < csb_tail->csb_indices; i++) + for (USHORT i = 0; i < csbTail->csb_indices; i++) { if (!(idx->idx_runtime_flags & idx_marker)) { - selected_idx = idx; + selectedIdx = idx; break; } @@ -2396,17 +2398,17 @@ } } - selected_idx->idx_runtime_flags |= idx_marker; - idx_sort.add(*selected_idx); + selectedIdx->idx_runtime_flags |= idx_marker; + idxSort.add(*selectedIdx); } // Finally store the right order in cbs_tail->csb_idx - index_desc* idx = csb_tail->csb_idx->items; + index_desc* idx = csbTail->csb_idx->items; - for (USHORT j = 0; j < csb_tail->csb_indices; j++) + for (USHORT j = 0; j < csbTail->csb_indices; j++) { idx->idx_runtime_flags &= ~idx_marker; - memcpy(idx, &idx_sort[j], sizeof(index_desc)); + memcpy(idx, &idxSort[j], sizeof(index_desc)); ++idx; } } Modified: firebird/trunk/src/jrd/RecordSourceNodes.h =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-25 01:01:22 UTC (rev 51471) +++ firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-25 01:35:33 UTC (rev 51472) @@ -62,7 +62,7 @@ stream = value; } - // Identify the streams that make up an RseNode. + // Identify the streams that make up a RseNode. virtual void getStreams(StreamsArray& list) const { list.add(getStream()); @@ -85,9 +85,9 @@ virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList) = 0; virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream) = 0; public: @@ -151,9 +151,9 @@ } virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream); public: @@ -206,9 +206,9 @@ virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream); private: @@ -255,13 +255,13 @@ virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream); private: - RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, NodeStack* parent_stack, + RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, NodeStack* parentStack, UCHAR shellStream); public: @@ -304,14 +304,14 @@ virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream); private: RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, UCHAR* streams, USHORT nstreams, - NodeStack* parent_stack, UCHAR shellStream); + NodeStack* parentStack, UCHAR shellStream); private: Firebird::Array<NestConst<RseNode> > clauses; // RseNode's for union @@ -361,9 +361,9 @@ virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream); private: @@ -435,9 +435,9 @@ virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parent_stack, stream_array_t& beds, stream_array_t& key_streams, - stream_array_t& local_streams, NodeStack& conjunct_stack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunct_count, + RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, + stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, + jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, bool innerSubStream); private: Modified: firebird/trunk/src/jrd/opt.cpp =================================================================== --- firebird/trunk/src/jrd/opt.cpp 2010-08-25 01:01:22 UTC (rev 51471) +++ firebird/trunk/src/jrd/opt.cpp 2010-08-25 01:35:33 UTC (rev 51472) @@ -781,20 +781,10 @@ } +// Compile and optimize a record selection expression into a set of record source blocks (rsb's). RecordSource* OPT_compile(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, NodeStack* parent_stack) { -/************************************** - * - * O P T _ c o m p i l e - * - ************************************** - * - * Functional description - * Compile and optimize a record selection expression into a - * set of record source blocks (rsb's). - * - **************************************/ stream_array_t streams, beds, local_streams, key_streams; StreamsArray outerStreams, subStreams; @@ -802,7 +792,6 @@ DEV_BLKCHK(rse, type_nod); SET_TDBB(tdbb); - //Database* dbb = tdbb->getDatabase(); #ifdef OPT_DEBUG if (opt_debug_flag != DEBUG_NONE && !opt_debug_file) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-25 03:10:19
|
Revision: 51473 http://firebird.svn.sourceforge.net/firebird/?rev=51473&view=rev Author: asfernandes Date: 2010-08-25 03:10:12 +0000 (Wed, 25 Aug 2010) Log Message: ----------- Move dozen of parameters of virtual/overriden function to OptimizerBlk Modified Paths: -------------- firebird/trunk/src/jrd/RecordSourceNodes.cpp firebird/trunk/src/jrd/RecordSourceNodes.h firebird/trunk/src/jrd/exe.h firebird/trunk/src/jrd/opt.cpp firebird/trunk/src/jrd/rse.h Modified: firebird/trunk/src/jrd/RecordSourceNodes.cpp =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-08-25 01:35:33 UTC (rev 51472) +++ firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-08-25 03:10:12 UTC (rev 51473) @@ -362,18 +362,14 @@ pass2(tdbb, csb); } -RecordSource* RelationSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) +RecordSource* RelationSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { fb_assert(stream <= MAX_UCHAR); - fb_assert(beds[0] < MAX_STREAMS && beds[0] < MAX_UCHAR); // debug check - //if (beds[0] >= MAX_STREAMS) // all builds check + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check // ERR_post(Arg::Gds(isc_too_many_contexts)); - beds[++beds[0]] = (UCHAR) stream; + opt->beds[++opt->beds[0]] = (UCHAR) stream; // we have found a base relation; record its stream // number in the streams array as a candidate for @@ -382,12 +378,12 @@ // TMN: Is the intention really to allow streams[0] to overflow? // I must assume that is indeed not the intention (not to mention // it would make code later on fail), so I added the following fb_assert. - fb_assert(streams[0] < MAX_STREAMS && streams[0] < MAX_UCHAR); + fb_assert(opt->compileStreams[0] < MAX_STREAMS && opt->compileStreams[0] < MAX_UCHAR); - streams[++streams[0]] = (UCHAR) stream; + opt->compileStreams[++opt->compileStreams[0]] = (UCHAR) stream; - if (rse->rse_jointype == blr_left) - outerStreams.add(stream); + if (opt->rse->rse_jointype == blr_left) + opt->outerStreams.add(stream); // if we have seen any booleans or sort fields, we may be able to // use an index to optimize them; retrieve the current format of @@ -396,20 +392,21 @@ // then no indices where retrieved. Added also OR check on // parentStack below. SF BUG # [ 508594 ] - if (conjunctCount || sort || aggregate || parentStack) + if (opt->conjunctCount || opt->rse->rse_sorted || opt->rse->rse_aggregate || opt->parentStack) { if (relation && !relation->rel_file && !relation->isVirtual()) { - csb->csb_rpt[stream].csb_indices = - BTR_all(tdbb, relation, &csb->csb_rpt[stream].csb_idx, relation->getPages(tdbb)); - sortIndicesBySelectivity(&csb->csb_rpt[stream]); - markIndices(&csb->csb_rpt[stream], relation->rel_id); + opt->opt_csb->csb_rpt[stream].csb_indices = + BTR_all(tdbb, relation, &opt->opt_csb->csb_rpt[stream].csb_idx, relation->getPages(tdbb)); + sortIndicesBySelectivity(&opt->opt_csb->csb_rpt[stream]); + markIndices(&opt->opt_csb->csb_rpt[stream], relation->rel_id); } else - csb->csb_rpt[stream].csb_indices = 0; + opt->opt_csb->csb_rpt[stream].csb_indices = 0; - const Format* format = CMP_format(tdbb, csb, stream); - csb->csb_rpt[stream].csb_cardinality = OPT_getRelationCardinality(tdbb, relation, format); + const Format* format = CMP_format(tdbb, opt->opt_csb, stream); + opt->opt_csb->csb_rpt[stream].csb_cardinality = + OPT_getRelationCardinality(tdbb, relation, format); } return NULL; @@ -594,22 +591,18 @@ pass2(tdbb, csb); } -RecordSource* ProcedureSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) +RecordSource* ProcedureSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { fb_assert(stream <= MAX_UCHAR); - fb_assert(beds[0] < MAX_STREAMS && beds[0] < MAX_UCHAR); // debug check - //if (beds[0] >= MAX_STREAMS) // all builds check + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check // ERR_post(Arg::Gds(isc_too_many_contexts)); - beds[++beds[0]] = (UCHAR) stream; + opt->beds[++opt->beds[0]] = (UCHAR) stream; RecordSource* rsb = generate(tdbb, opt); - fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); - localStreams[++localStreams[0]] = stream; + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = stream; return rsb; } @@ -765,30 +758,26 @@ return false; } -RecordSource* AggregateSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) +RecordSource* AggregateSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { fb_assert(stream <= MAX_UCHAR); - fb_assert(beds[0] < MAX_STREAMS && beds[0] < MAX_UCHAR); // debug check - //if (beds[0] >= MAX_STREAMS) // all builds check + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check // ERR_post(Arg::Gds(isc_too_many_contexts)); - beds[++beds[0]] = (UCHAR) stream; + opt->beds[++opt->beds[0]] = (UCHAR) stream; NodeStack::const_iterator stackEnd; - if (parentStack) - stackEnd = conjunctStack.merge(*parentStack); + if (opt->parentStack) + stackEnd = opt->conjunctStack.merge(*opt->parentStack); - RecordSource* rsb = generate(tdbb, opt, &conjunctStack, stream); + RecordSource* rsb = generate(tdbb, opt, &opt->conjunctStack, stream); - if (parentStack) - conjunctStack.split(stackEnd, *parentStack); + if (opt->parentStack) + opt->conjunctStack.split(stackEnd, *opt->parentStack); - fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); - localStreams[++localStreams[0]] = stream; + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = stream; return rsb; } @@ -1033,27 +1022,23 @@ return false; } -RecordSource* UnionSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) +RecordSource* UnionSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { - const SSHORT i = (SSHORT) keyStreams[0]; - computeDbKeyStreams(keyStreams); + const SSHORT i = (SSHORT) opt->keyStreams[0]; + computeDbKeyStreams(opt->keyStreams); NodeStack::const_iterator stackEnd; - if (parentStack) - stackEnd = conjunctStack.merge(*parentStack); + if (opt->parentStack) + stackEnd = opt->conjunctStack.merge(*opt->parentStack); - RecordSource* rsb = generate(tdbb, opt, keyStreams + i + 1, - (USHORT) (keyStreams[0] - i), &conjunctStack, stream); + RecordSource* rsb = generate(tdbb, opt, opt->keyStreams + i + 1, + (USHORT) (opt->keyStreams[0] - i), &opt->conjunctStack, stream); - if (parentStack) - conjunctStack.split(stackEnd, *parentStack); + if (opt->parentStack) + opt->conjunctStack.split(stackEnd, *opt->parentStack); - fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); - localStreams[++localStreams[0]] = stream; + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = stream; return rsb; } @@ -1332,11 +1317,7 @@ return false; } -RecordSource* WindowSourceNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) +RecordSource* WindowSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { const jrd_nod* nodWindows = windows; @@ -1345,25 +1326,25 @@ SSHORT partStream = (USHORT)(IPTR) nodWindows->nod_arg[i]->nod_arg[e_part_stream]; fb_assert(partStream <= MAX_UCHAR); - fb_assert(beds[0] < MAX_STREAMS && beds[0] < MAX_UCHAR); // debug check - //if (beds[0] >= MAX_STREAMS) // all builds check + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check // ERR_post(Arg::Gds(isc_too_many_contexts)); - beds[++beds[0]] = (UCHAR) partStream; + opt->beds[++opt->beds[0]] = (UCHAR) partStream; } NodeStack deliverStack; - RecordSource* rsb = FB_NEW(*tdbb->getDefaultPool()) WindowedStream(csb, windows, - OPT_compile(tdbb, csb, this->rse, &deliverStack)); + RecordSource* rsb = FB_NEW(*tdbb->getDefaultPool()) WindowedStream(opt->opt_csb, windows, + OPT_compile(tdbb, opt->opt_csb, rse, &deliverStack)); StreamsArray rsbStreams; rsb->findUsedStreams(rsbStreams); for (StreamsArray::iterator i = rsbStreams.begin(); i != rsbStreams.end(); ++i) { - fb_assert(localStreams[0] < MAX_STREAMS && localStreams[0] < MAX_UCHAR); - localStreams[++localStreams[0]] = *i; + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = *i; } return rsb; @@ -1610,41 +1591,37 @@ return false; } -RecordSource* RseNode::compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) +RecordSource* RseNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { // for nodes which are not relations, generate an rsb to // represent that work has to be done to retrieve them; // find all the substreams involved and compile them as well - computeRseStreams(csb, beds); - computeRseStreams(csb, localStreams); - computeDbKeyStreams(keyStreams); + computeRseStreams(opt->opt_csb, opt->beds); + computeRseStreams(opt->opt_csb, opt->localStreams); + computeDbKeyStreams(opt->keyStreams); RecordSource* rsb; // pass RseNode boolean only to inner substreams because join condition // should never exclude records from outer substreams - if (rse->rse_jointype == blr_inner || (rse->rse_jointype == blr_left && innerSubStream)) + if (opt->rse->rse_jointype == blr_inner || (opt->rse->rse_jointype == blr_left && innerSubStream)) { // AB: For an (X LEFT JOIN Y) mark the outer-streams (X) as // active because the inner-streams (Y) are always "dependent" // on the outer-streams. So that index retrieval nodes could be made. // For an INNER JOIN mark previous generated RecordSource's as active. - if (rse->rse_jointype == blr_left) + if (opt->rse->rse_jointype == blr_left) { - for (StreamsArray::iterator i = outerStreams.begin(); i != outerStreams.end(); ++i) - csb->csb_rpt[*i].csb_flags |= csb_active; + for (StreamsArray::iterator i = opt->outerStreams.begin(); i != opt->outerStreams.end(); ++i) + opt->opt_csb->csb_rpt[*i].csb_flags |= csb_active; } - //const NodeStack::iterator stackSavepoint(conjunctStack); + //const NodeStack::iterator stackSavepoint(opt->conjunctStack); NodeStack::const_iterator stackEnd; NodeStack deliverStack; - if (rse->rse_jointype != blr_inner) + if (opt->rse->rse_jointype != blr_inner) { // Make list of nodes that can be delivered to an outer-stream. // In fact these are all nodes except when a IS NULL (nod_missing) @@ -1652,8 +1629,8 @@ // Note! Don't forget that this can be burried inside a expression // such as "CASE WHEN (FieldX IS NULL) THEN 0 ELSE 1 END = 0" NodeStack::iterator stackItem; - if (parentStack) - stackItem = *parentStack; + if (opt->parentStack) + stackItem = *opt->parentStack; for (; stackItem.hasData(); ++stackItem) { @@ -1663,35 +1640,35 @@ deliverStack.push(deliverNode); } - stackEnd = conjunctStack.merge(deliverStack); + stackEnd = opt->conjunctStack.merge(deliverStack); } else { - if (parentStack) - stackEnd = conjunctStack.merge(*parentStack); + if (opt->parentStack) + stackEnd = opt->conjunctStack.merge(*opt->parentStack); } - rsb = OPT_compile(tdbb, csb, this, &conjunctStack); + rsb = OPT_compile(tdbb, opt->opt_csb, this, &opt->conjunctStack); - if (rse->rse_jointype != blr_inner) + if (opt->rse->rse_jointype != blr_inner) { // Remove previously added parent conjuctions from the stack. - conjunctStack.split(stackEnd, deliverStack); + opt->conjunctStack.split(stackEnd, deliverStack); } else { - if (parentStack) - conjunctStack.split(stackEnd, *parentStack); + if (opt->parentStack) + opt->conjunctStack.split(stackEnd, *opt->parentStack); } - if (rse->rse_jointype == blr_left) + if (opt->rse->rse_jointype == blr_left) { - for (StreamsArray::iterator i = outerStreams.begin(); i != outerStreams.end(); ++i) - csb->csb_rpt[*i].csb_flags &= ~csb_active; + for (StreamsArray::iterator i = opt->outerStreams.begin(); i != opt->outerStreams.end(); ++i) + opt->opt_csb->csb_rpt[*i].csb_flags &= ~csb_active; } } else - rsb = OPT_compile(tdbb, csb, this, parentStack); + rsb = OPT_compile(tdbb, opt->opt_csb, this, opt->parentStack); return rsb; } Modified: firebird/trunk/src/jrd/RecordSourceNodes.h =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-25 01:35:33 UTC (rev 51472) +++ firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-25 03:10:12 UTC (rev 51473) @@ -84,11 +84,7 @@ bool allowOnlyCurrentStream, jrd_nod* value) = 0; virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList) = 0; - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream) = 0; + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) = 0; public: const Type type; @@ -150,11 +146,7 @@ { } - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream); + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); public: jrd_rel* relation; @@ -205,11 +197,7 @@ bool allowOnlyCurrentStream, jrd_nod* value); virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream); + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); private: ProcedureScan* generate(thread_db* tdbb, OptimizerBlk* opt); @@ -254,11 +242,7 @@ bool allowOnlyCurrentStream, jrd_nod* value); virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream); + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); private: RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, NodeStack* parentStack, @@ -303,11 +287,7 @@ bool allowOnlyCurrentStream, jrd_nod* value); virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream); + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); private: RecordSource* generate(thread_db* tdbb, OptimizerBlk* opt, UCHAR* streams, USHORT nstreams, @@ -360,11 +340,7 @@ bool allowOnlyCurrentStream, jrd_nod* value); virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream); + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); private: NestConst<RseNode> rse; @@ -434,11 +410,7 @@ bool allowOnlyCurrentStream, jrd_nod* value); virtual void findDependentFromStreams(const OptimizerRetrieval* optRet, SortedStreamList* streamList); - virtual RecordSource* compile(thread_db* tdbb, CompilerScratch* csb, OptimizerBlk* opt, - RseNode* rse, NodeStack* parentStack, stream_array_t& beds, stream_array_t& keyStreams, - stream_array_t& localStreams, NodeStack& conjunctStack, stream_array_t& streams, - jrd_nod* sort, jrd_nod* aggregate, StreamsArray& outerStreams, SLONG conjunctCount, - bool innerSubStream); + virtual RecordSource* compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream); private: void computeRseStreams(const CompilerScratch* csb, UCHAR* streams) const; Modified: firebird/trunk/src/jrd/exe.h =================================================================== --- firebird/trunk/src/jrd/exe.h 2010-08-25 01:35:33 UTC (rev 51472) +++ firebird/trunk/src/jrd/exe.h 2010-08-25 03:10:12 UTC (rev 51473) @@ -918,10 +918,6 @@ // declared as varchar const int XCP_MESSAGE_LENGTH = 1023 - sizeof(USHORT); -typedef Firebird::HalfStaticArray<UCHAR, OPT_STATIC_ITEMS> StreamsArray; -typedef Firebird::SortedArray<int> SortedStreamList; -typedef UCHAR stream_array_t[MAX_STREAMS + 1]; - } // namespace Jrd #endif // JRD_EXE_H Modified: firebird/trunk/src/jrd/opt.cpp =================================================================== --- firebird/trunk/src/jrd/opt.cpp 2010-08-25 01:35:33 UTC (rev 51472) +++ firebird/trunk/src/jrd/opt.cpp 2010-08-25 03:10:12 UTC (rev 51473) @@ -782,12 +782,9 @@ // Compile and optimize a record selection expression into a set of record source blocks (rsb's). -RecordSource* OPT_compile(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, - NodeStack* parent_stack) +RecordSource* OPT_compile(thread_db* tdbb, CompilerScratch* csb, RseNode* const rse, + NodeStack* const parent_stack) { - stream_array_t streams, beds, local_streams, key_streams; - StreamsArray outerStreams, subStreams; - DEV_BLKCHK(csb, type_csb); DEV_BLKCHK(rse, type_nod); @@ -808,7 +805,8 @@ // memory will then be in csb->csb_rpt[stream].csb_idx_allocation, which // gets cleaned up before this function exits. - AutoPtr<OptimizerBlk> opt(FB_NEW(*tdbb->getDefaultPool()) OptimizerBlk(tdbb->getDefaultPool())); + AutoPtr<OptimizerBlk> opt(FB_NEW(*tdbb->getDefaultPool()) OptimizerBlk(tdbb->getDefaultPool(), + rse, parent_stack)); opt->opt_streams.grow(csb->csb_n_stream); RecordSource* rsb = NULL; @@ -816,10 +814,7 @@ opt->opt_csb = csb; - beds[0] = streams[0] = key_streams[0] = 0; - NodeStack conjunct_stack; RiverList rivers; - SLONG conjunct_count = 0; check_sorts(rse); jrd_nod* sort = rse->rse_sorted; @@ -829,18 +824,16 @@ // put any additional booleans on the conjunct stack, and see if we // can generate additional booleans by associativity--this will help // to utilize indices that we might not have noticed - if (rse->rse_boolean) { - conjunct_count = decompose(tdbb, rse->rse_boolean, conjunct_stack, csb); - } + if (rse->rse_boolean) + opt->conjunctCount = decompose(tdbb, rse->rse_boolean, opt->conjunctStack, csb); - conjunct_count += distribute_equalities(conjunct_stack, csb, conjunct_count); + opt->conjunctCount += distribute_equalities(opt->conjunctStack, csb, opt->conjunctCount); // AB: If we have limit our retrieval with FIRST / SKIP syntax then // we may not deliver above conditions (from higher rse's) to this // rse, because the results should be consistent. - if (rse->rse_skip || rse->rse_first) { - parent_stack = NULL; - } + if (rse->rse_skip || rse->rse_first) + opt->parentStack = NULL; // clear the csb_active flag of all streams in the RseNode set_rse_inactive(csb, rse); @@ -858,14 +851,15 @@ { RecordSourceNode* node = *ptr; - local_streams[0] = 0; + opt->localStreams[0] = 0; + fb_assert(sort == rse->rse_sorted); + fb_assert(aggregate == rse->rse_aggregate); + // find the stream number and place it at the end of the beds array // (if this is really a stream and not another RseNode) - rsb = node->compile(tdbb, csb, opt, rse, parent_stack, beds, key_streams, - local_streams, conjunct_stack, streams, sort, aggregate, outerStreams, - conjunct_count, (ptr - rse->rse_relations.begin() == 1)); + rsb = node->compile(tdbb, opt, (ptr - rse->rse_relations.begin() == 1)); // if an rsb has been generated, we have a non-relation; // so it forms a river of its own since it is separately @@ -877,16 +871,14 @@ if (rse->rse_jointype == blr_inner || (rse->rse_jointype == blr_left && (ptr - rse->rse_relations.begin()) == 0)) { - rsb->findUsedStreams(subStreams); + rsb->findUsedStreams(opt->subStreams); // Save also the outer streams if (rse->rse_jointype == blr_left) - { - rsb->findUsedStreams(outerStreams); - } + rsb->findUsedStreams(opt->outerStreams); } - const size_t count = local_streams[0]; - UCHAR* const streams = local_streams + 1; + const size_t count = opt->localStreams[0]; + UCHAR* const streams = opt->localStreams + 1; River* const river = FB_NEW(*tdbb->getDefaultPool()) River(csb, rsb, count, streams); river->deactivate(csb); rivers.add(river); @@ -896,9 +888,8 @@ // this is an attempt to make sure we have a large enough cache to // efficiently retrieve this query; make sure the cache has a minimum // number of pages for each stream in the RseNode (the number is just a guess) - if (streams[0] > 5) { - CCH_expand(tdbb, (ULONG) (streams[0] * CACHE_PAGES_PER_STREAM)); - } + if (opt->compileStreams[0] > 5) + CCH_expand(tdbb, (ULONG) (opt->compileStreams[0] * CACHE_PAGES_PER_STREAM)); // At this point we are ready to start optimizing. // We will use the opt block to hold information of @@ -906,10 +897,10 @@ // around for the rest of the optimization process. // Set base-point before the parent/distributed nodes begin. - const USHORT base_count = (USHORT) conjunct_count; + const USHORT base_count = (USHORT) opt->conjunctCount; opt->opt_base_conjuncts = base_count; - // AB: Add parent conjunctions to conjunct_stack, keep in mind + // AB: Add parent conjunctions to opt->conjunctStack, keep in mind // the outer-streams! For outer streams put missing (IS NULL) // conjunctions in the missing_stack. // @@ -925,10 +916,10 @@ USHORT parent_count = 0, distributed_count = 0; NodeStack missing_stack; - if (parent_stack) + if (opt->parentStack) { - for (NodeStack::iterator iter(*parent_stack); - iter.hasData() && conjunct_count < MAX_CONJUNCTS; ++iter) + for (NodeStack::iterator iter(*opt->parentStack); + iter.hasData() && opt->conjunctCount < MAX_CONJUNCTS; ++iter) { jrd_nod* const node = iter.object(); @@ -943,15 +934,15 @@ } else { - conjunct_stack.push(node); - conjunct_count++; + opt->conjunctStack.push(node); + opt->conjunctCount++; parent_count++; } } // We've now merged parent, try again to make more conjunctions. - distributed_count = distribute_equalities(conjunct_stack, csb, conjunct_count); - conjunct_count += distributed_count; + distributed_count = distribute_equalities(opt->conjunctStack, csb, opt->conjunctCount); + opt->conjunctCount += distributed_count; } // The newly created conjunctions belong to the base conjunctions. @@ -959,10 +950,10 @@ opt->opt_base_parent_conjuncts = opt->opt_base_conjuncts + distributed_count; // Set base-point before the parent IS NULL nodes begin - opt->opt_base_missing_conjuncts = (USHORT) conjunct_count; + opt->opt_base_missing_conjuncts = (USHORT) opt->conjunctCount; // Check if size of optimizer block exceeded. - if (conjunct_count > MAX_CONJUNCTS) + if (opt->conjunctCount > MAX_CONJUNCTS) { ERR_post(Arg::Gds(isc_optimizer_blk_exc)); // Msg442: size of optimizer block exceeded @@ -970,11 +961,11 @@ // Put conjunctions in opt structure. // Note that it's a stack and we get the nodes in reversed order from the stack. - opt->opt_conjuncts.grow(conjunct_count); + opt->opt_conjuncts.grow(opt->conjunctCount); SSHORT nodeBase = -1, j = -1; - for (SLONG i = conjunct_count; i > 0; i--, j--) + for (SLONG i = opt->conjunctCount; i > 0; i--, j--) { - jrd_nod* const node = conjunct_stack.pop(); + jrd_nod* const node = opt->conjunctStack.pop(); if (i == base_count) { @@ -982,13 +973,13 @@ j = base_count - 1; nodeBase = 0; } - else if (i == conjunct_count - distributed_count) + else if (i == opt->conjunctCount - distributed_count) { // The parent conjunctions j = parent_count - 1; nodeBase = opt->opt_base_parent_conjuncts; } - else if (i == conjunct_count) + else if (i == opt->conjunctCount) { // The new conjunctions created by "distribution" from the stack j = distributed_count - 1; @@ -1001,13 +992,13 @@ // Put the parent missing nodes on the stack for (NodeStack::iterator iter(missing_stack); - iter.hasData() && conjunct_count < MAX_CONJUNCTS; ++iter) + iter.hasData() && opt->conjunctCount < MAX_CONJUNCTS; ++iter) { jrd_nod* const node = iter.object(); - opt->opt_conjuncts.grow(conjunct_count + 1); - opt->opt_conjuncts[conjunct_count].opt_conjunct_node = node; - conjunct_count++; + opt->opt_conjuncts.grow(opt->conjunctCount + 1); + opt->opt_conjuncts[opt->conjunctCount].opt_conjunct_node = node; + opt->conjunctCount++; } // Deoptimize some conjuncts in advance @@ -1029,7 +1020,7 @@ } // AB: Mark the previous used streams (sub-RseNode's) as active - for (StreamsArray::iterator i = subStreams.begin(); i != subStreams.end(); ++i) + for (StreamsArray::iterator i = opt->subStreams.begin(); i != opt->subStreams.end(); ++i) csb->csb_rpt[*i].csb_flags |= csb_active; // outer joins require some extra processing @@ -1055,11 +1046,11 @@ // AB: Mark the previous used streams (sub-RseNode's) again // as active, because a SORT/MERGE could reset the flags - for (StreamsArray::iterator i = subStreams.begin(); i != subStreams.end(); ++i) + for (StreamsArray::iterator i = opt->subStreams.begin(); i != opt->subStreams.end(); ++i) csb->csb_rpt[*i].csb_flags |= csb_active; } - fb_assert(streams[0] != 1 || csb->csb_rpt[streams[1]].csb_relation != 0); + fb_assert(opt->compileStreams[0] != 1 || csb->csb_rpt[opt->compileStreams[1]].csb_relation != 0); while (true) { @@ -1070,7 +1061,7 @@ // a stream depends (index) on the active rivers. stream_array_t dependent_streams, free_streams; dependent_streams[0] = free_streams[0] = 0; - find_index_relationship_streams(tdbb, opt, streams, dependent_streams, free_streams); + find_index_relationship_streams(tdbb, opt, opt->compileStreams, dependent_streams, free_streams); // If we have dependent and free streams then we can't rely on // the sort node to be used for index navigation. @@ -1084,7 +1075,7 @@ { // copy free streams for (USHORT i = 0; i <= free_streams[0]; i++) { - streams[i] = free_streams[i]; + opt->compileStreams[i] = free_streams[i]; } // Make rivers from the dependent streams @@ -1114,7 +1105,7 @@ } // attempt to form joins in decreasing order of desirability - gen_join(tdbb, opt, streams, rivers, &sort, rse->rse_plan); + gen_join(tdbb, opt, opt->compileStreams, rivers, &sort, rse->rse_plan); // If there are multiple rivers, try some hashing or sort/merging while (gen_equi_join(tdbb, opt, rivers)) @@ -1143,19 +1134,18 @@ // check index usage in all the base streams to ensure // that any user-specified access plan is followed - for (USHORT i = 1; i <= streams[0]; i++) { - check_indices(&csb->csb_rpt[streams[i]]); - } + for (USHORT i = 1; i <= opt->compileStreams[0]; i++) + check_indices(&csb->csb_rpt[opt->compileStreams[i]]); if (project || sort) { // Eliminate any duplicate dbkey streams - const UCHAR* const b_end = beds + beds[0]; - const UCHAR* const k_end = key_streams + key_streams[0]; - UCHAR* k = &key_streams[1]; + const UCHAR* const b_end = opt->beds + opt->beds[0]; + const UCHAR* const k_end = opt->keyStreams + opt->keyStreams[0]; + UCHAR* k = &opt->keyStreams[1]; for (const UCHAR* p2 = k; p2 <= k_end; p2++) { - const UCHAR* q = &beds[1]; + const UCHAR* q = &opt->beds[1]; while (q <= b_end && *q != *p2) { q++; } @@ -1163,16 +1153,16 @@ *k++ = *p2; } } - key_streams[0] = k - &key_streams[1]; + opt->keyStreams[0] = k - &opt->keyStreams[1]; // Handle project clause, if present if (project) { - rsb = OPT_gen_sort(tdbb, opt->opt_csb, beds, key_streams, rsb, project, true); + rsb = OPT_gen_sort(tdbb, opt->opt_csb, opt->beds, opt->keyStreams, rsb, project, true); } // Handle sort clause if present if (sort) { - rsb = OPT_gen_sort(tdbb, opt->opt_csb, beds, key_streams, rsb, sort, false); + rsb = OPT_gen_sort(tdbb, opt->opt_csb, opt->beds, opt->keyStreams, rsb, sort, false); } } @@ -1190,9 +1180,9 @@ } // release memory allocated for index descriptions - for (USHORT i = 1; i <= streams[0]; ++i) + for (USHORT i = 1; i <= opt->compileStreams[0]; ++i) { - const USHORT loopStream = streams[i]; + const USHORT loopStream = opt->compileStreams[i]; delete csb->csb_rpt[loopStream].csb_idx; csb->csb_rpt[loopStream].csb_idx = NULL; @@ -1215,9 +1205,9 @@ } // try catch (const Firebird::Exception&) { - for (USHORT i = 1; i <= streams[0]; ++i) + for (USHORT i = 1; i <= opt->compileStreams[0]; ++i) { - const USHORT loopStream = streams[i]; + const USHORT loopStream = opt->compileStreams[i]; delete csb->csb_rpt[loopStream].csb_idx; csb->csb_rpt[loopStream].csb_idx = NULL; csb->csb_rpt[loopStream].csb_indices = 0; // Probably needed to be safe @@ -1228,9 +1218,9 @@ if (rse->flags & RseNode::FLAG_WRITELOCK) { - for (USHORT i = 1; i <= streams[0]; ++i) + for (USHORT i = 1; i <= opt->compileStreams[0]; ++i) { - const USHORT loopStream = streams[i]; + const USHORT loopStream = opt->compileStreams[i]; csb->csb_rpt[loopStream].csb_flags |= csb_update; } } Modified: firebird/trunk/src/jrd/rse.h =================================================================== --- firebird/trunk/src/jrd/rse.h 2010-08-25 01:35:33 UTC (rev 51472) +++ firebird/trunk/src/jrd/rse.h 2010-08-25 03:10:12 UTC (rev 51473) @@ -71,33 +71,60 @@ // in various arrays. Larger numbers will have to be allocated dynamically const int OPT_STATIC_ITEMS = 16; +typedef Firebird::HalfStaticArray<UCHAR, OPT_STATIC_ITEMS> StreamsArray; +typedef Firebird::SortedArray<int> SortedStreamList; +typedef UCHAR stream_array_t[MAX_STREAMS + 1]; +class RseNode; + // General optimizer block class OptimizerBlk : public pool_alloc<type_opt> { public: - CompilerScratch* opt_csb; // compiler scratch block + OptimizerBlk(MemoryPool* pool, RseNode* aRse, NodeStack* aParentStack) + : opt_conjuncts(*pool), + opt_streams(*pool), + rse(aRse), + parentStack(aParentStack), + outerStreams(*pool), + subStreams(*pool), + conjunctStack(*pool), + conjunctCount(0) + { + compileStreams[0] = beds[0] = localStreams[0] = keyStreams[0] = 0; + } + + CompilerScratch* opt_csb; // compiler scratch block double opt_best_cost; // cost of best join order USHORT opt_best_count; // longest length of indexable streams USHORT opt_base_conjuncts; // number of conjuncts in our rse, next conjuncts are distributed parent USHORT opt_base_parent_conjuncts; // number of conjuncts in our rse + distributed with parent, next are parent USHORT opt_base_missing_conjuncts; // number of conjuncts in our and parent rse, but without missing + struct opt_conjunct { // Conjunctions and their options jrd_nod* opt_conjunct_node; // conjunction UCHAR opt_conjunct_flags; }; + struct opt_stream { // Streams and their options USHORT opt_best_stream; // stream in best join order seen so far USHORT opt_stream_number; // stream in position of join order }; + Firebird::HalfStaticArray<opt_conjunct, OPT_STATIC_ITEMS> opt_conjuncts; Firebird::HalfStaticArray<opt_stream, OPT_STATIC_ITEMS> opt_streams; - OptimizerBlk(MemoryPool* pool) : opt_conjuncts(*pool), opt_streams(*pool) {} + + RseNode* const rse; + NodeStack* parentStack; + StreamsArray outerStreams, subStreams; + NodeStack conjunctStack; + SLONG conjunctCount; + stream_array_t compileStreams, beds, localStreams, keyStreams; }; // values for opt_conjunct_flags This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-25 15:52:53
|
Revision: 51482 http://firebird.svn.sourceforge.net/firebird/?rev=51482&view=rev Author: asfernandes Date: 2010-08-25 15:52:46 +0000 (Wed, 25 Aug 2010) Log Message: ----------- Rework WindowSourceNode to use type-safe partitions Modified Paths: -------------- firebird/trunk/src/jrd/RecordSourceNodes.cpp firebird/trunk/src/jrd/RecordSourceNodes.h firebird/trunk/src/jrd/exe.h firebird/trunk/src/jrd/recsrc/RecordSource.h firebird/trunk/src/jrd/recsrc/WindowedStream.cpp Modified: firebird/trunk/src/jrd/RecordSourceNodes.cpp =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-08-25 13:36:24 UTC (rev 51481) +++ firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-08-25 15:52:46 UTC (rev 51482) @@ -1137,18 +1137,15 @@ node->rse = RseNode::getFrom(PAR_parse_node(tdbb, csb, TYPE_RSE)); unsigned partitionCount = csb->csb_blr_reader.getByte(); - NodeStack stack; for (unsigned i = 0; i < partitionCount; ++i) - stack.push(parsePartitionBy(tdbb, csb)); + node->parsePartitionBy(tdbb, csb); - node->windows = PAR_make_list(tdbb, stack); - return node; } // Parse PARTITION BY subclauses of window functions. -jrd_nod* WindowSourceNode::parsePartitionBy(thread_db* tdbb, CompilerScratch* csb) +void WindowSourceNode::parsePartitionBy(thread_db* tdbb, CompilerScratch* csb) { SET_TDBB(tdbb); @@ -1156,42 +1153,35 @@ PAR_syntax_error(csb, "blr_partition_by"); SSHORT context; - SSHORT partitionStream = PAR_context(csb, &context); + Partition partition; + partition.stream = PAR_context(csb, &context); - jrd_nod* list = PAR_make_node(tdbb, e_part_length); - list->nod_type = nod_list; - list->nod_count = e_part_count; - const UCHAR count = csb->csb_blr_reader.getByte(); if (count != 0) { - jrd_nod*& groupNode = list->nod_arg[e_part_group]; - jrd_nod*& regroupNode = list->nod_arg[e_part_regroup]; + partition.group = PAR_args(tdbb, csb, VALUE, count, count * 3); + partition.regroup = PAR_args(tdbb, csb, VALUE, count, count); - groupNode = PAR_args(tdbb, csb, VALUE, count, count * 3); - regroupNode = PAR_args(tdbb, csb, VALUE, count, count); - // We have allocated groupNode with bigger length than expressions. This is to use in // OPT_gen_sort. Now fill that info. - groupNode->nod_type = nod_sort; + partition.group->nod_type = nod_sort; for (unsigned i = 0; i < count; ++i) { - groupNode->nod_arg[count + i] = (jrd_nod*)(IPTR) false; // ascending - groupNode->nod_arg[count * 2 + i] = (jrd_nod*)(IPTR) rse_nulls_first; + partition.group->nod_arg[count + i] = (jrd_nod*)(IPTR) false; // ascending + partition.group->nod_arg[count * 2 + i] = (jrd_nod*)(IPTR) rse_nulls_first; } } if (csb->csb_blr_reader.getByte() != blr_sort) PAR_syntax_error(csb, "blr_sort"); - list->nod_arg[e_part_order] = PAR_sort(tdbb, csb, true, true); - list->nod_arg[e_part_map] = parseMap(tdbb, csb, partitionStream); - list->nod_arg[e_part_stream] = (jrd_nod*)(IPTR) partitionStream; + partition.order = PAR_sort(tdbb, csb, true, true); + partition.map = parseMap(tdbb, csb, partition.stream); - return list; + partitions.add(partition); } WindowSourceNode* WindowSourceNode::copy(thread_db* tdbb, NodeCopier& copier) @@ -1203,33 +1193,25 @@ *tdbb->getDefaultPool()); newSource->rse = rse->copy(tdbb, copier); + + Partition* copyPartition = newSource->partitions.getBuffer(partitions.getCount()); - jrd_nod* inputWindows = windows; - - jrd_nod* copyWindows = newSource->windows = PAR_make_node(tdbb, inputWindows->nod_count); - copyWindows->nod_type = inputWindows->nod_type; - copyWindows->nod_count = inputWindows->nod_count; - - for (unsigned i = 0; i < inputWindows->nod_count; ++i) + for (Partition* inputPartition = partitions.begin(); + inputPartition != partitions.end(); + ++inputPartition, ++copyPartition) { - jrd_nod* inputPartition = inputWindows->nod_arg[i]; + fb_assert(inputPartition->stream <= MAX_STREAMS); - jrd_nod* copyPartition = copyWindows->nod_arg[i] = PAR_make_node(tdbb, e_part_length); - copyPartition->nod_type = inputPartition->nod_type; - copyPartition->nod_count = inputPartition->nod_count; + copyPartition->stream = copier.csb->nextStream(); + // fb_assert(copyPartition->stream <= MAX_UCHAR); - USHORT oldStream = (USHORT)(IPTR) inputPartition->nod_arg[e_part_stream]; - fb_assert(oldStream <= MAX_STREAMS); + copier.remap[inputPartition->stream] = (UCHAR) copyPartition->stream; + CMP_csb_element(copier.csb, copyPartition->stream); - USHORT newStream = copier.csb->nextStream(); - - copyPartition->nod_arg[e_part_stream] = (jrd_nod*)(IPTR) newStream; - // fb_assert(newStream <= MAX_UCHAR); - copier.remap[oldStream] = (UCHAR) newStream; - CMP_csb_element(copier.csb, newStream); - - for (unsigned j = 0; j < copyPartition->nod_count; ++j) - copyPartition->nod_arg[j] = copier.copy(tdbb, inputPartition->nod_arg[j]); + copyPartition->group = copier.copy(tdbb, inputPartition->group); + copyPartition->regroup = copier.copy(tdbb, inputPartition->regroup); + copyPartition->order = copier.copy(tdbb, inputPartition->order); + copyPartition->map = copier.copy(tdbb, inputPartition->map); } return newSource; @@ -1242,18 +1224,22 @@ void WindowSourceNode::pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view) { - const jrd_nod* nodWindows = windows; - - for (unsigned i = 0; i < nodWindows->nod_count; ++i) + for (Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) { - USHORT partStream = (USHORT)(IPTR) nodWindows->nod_arg[i]->nod_arg[e_part_stream]; - fb_assert(partStream <= MAX_STREAMS); - csb->csb_rpt[partStream].csb_flags |= csb_no_dbkey; + fb_assert(partition->stream <= MAX_STREAMS); + csb->csb_rpt[partition->stream].csb_flags |= csb_no_dbkey; } rse->ignoreDbKey(tdbb, csb, view); rse->pass1(tdbb, csb, csb->csb_view); - windows = CMP_pass1(tdbb, csb, windows); + + for (Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) + { + partition->group = CMP_pass1(tdbb, csb, partition->group); + partition->regroup = CMP_pass1(tdbb, csb, partition->regroup); + partition->order = CMP_pass1(tdbb, csb, partition->order); + partition->map = CMP_pass1(tdbb, csb, partition->map); + } } void WindowSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, @@ -1268,46 +1254,37 @@ { rse->pass2Rse(tdbb, csb); - jrd_nod* nodWindows = windows; - - for (unsigned i = 0; i < nodWindows->nod_count; ++i) + for (Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) { - CMP_pass2(tdbb, csb, nodWindows->nod_arg[i]->nod_arg[e_part_map], nodWindows->nod_arg[i]); - CMP_pass2(tdbb, csb, nodWindows->nod_arg[i]->nod_arg[e_part_group], nodWindows->nod_arg[i]); - CMP_pass2(tdbb, csb, nodWindows->nod_arg[i]->nod_arg[e_part_order], nodWindows->nod_arg[i]); + CMP_pass2(tdbb, csb, partition->map, NULL); + CMP_pass2(tdbb, csb, partition->group, NULL); + CMP_pass2(tdbb, csb, partition->order, NULL); - const USHORT partStream = (SSHORT)(IPTR) nodWindows->nod_arg[i]->nod_arg[e_part_stream]; - fb_assert(partStream <= MAX_STREAMS); + fb_assert(partition->stream <= MAX_STREAMS); - processMap(tdbb, csb, nodWindows->nod_arg[i]->nod_arg[e_part_map], - &csb->csb_rpt[partStream].csb_internal_format); - csb->csb_rpt[partStream].csb_format = csb->csb_rpt[partStream].csb_internal_format; + processMap(tdbb, csb, partition->map, + &csb->csb_rpt[partition->stream].csb_internal_format); + csb->csb_rpt[partition->stream].csb_format = + csb->csb_rpt[partition->stream].csb_internal_format; } - for (unsigned i = 0; i < nodWindows->nod_count; ++i) - CMP_pass2(tdbb, csb, nodWindows->nod_arg[i]->nod_arg[e_part_regroup], nodWindows->nod_arg[i]); + for (Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) + CMP_pass2(tdbb, csb, partition->regroup, NULL); } void WindowSourceNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) { - const jrd_nod* nodWindows = windows; - pass2(tdbb, csb); - for (unsigned i = 0; i < nodWindows->nod_count; ++i) - { - const SSHORT partStream = (USHORT)(IPTR) nodWindows->nod_arg[i]->nod_arg[e_part_stream]; - csb->csb_rpt[partStream].csb_flags |= csb_active; - } + for (Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) + csb->csb_rpt[partition->stream].csb_flags |= csb_active; } bool WindowSourceNode::containsStream(USHORT checkStream) const { - const jrd_nod* nodWindows = windows; - - for (unsigned i = 0; i < nodWindows->nod_count; ++i) + for (const Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) { - if (checkStream == (USHORT)(IPTR) nodWindows->nod_arg[i]->nod_arg[e_part_stream]) + if (checkStream == partition->stream) return true; // do not mark as variant } @@ -1319,23 +1296,19 @@ RecordSource* WindowSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) { - const jrd_nod* nodWindows = windows; - - for (unsigned i = 0; i < nodWindows->nod_count; ++i) + for (Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) { - SSHORT partStream = (USHORT)(IPTR) nodWindows->nod_arg[i]->nod_arg[e_part_stream]; - - fb_assert(partStream <= MAX_UCHAR); + fb_assert(partition->stream <= MAX_UCHAR); fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check //if (opt->beds[0] >= MAX_STREAMS) // all builds check // ERR_post(Arg::Gds(isc_too_many_contexts)); - opt->beds[++opt->beds[0]] = (UCHAR) partStream; + opt->beds[++opt->beds[0]] = (UCHAR) partition->stream; } NodeStack deliverStack; - RecordSource* rsb = FB_NEW(*tdbb->getDefaultPool()) WindowedStream(opt->opt_csb, windows, + RecordSource* rsb = FB_NEW(*tdbb->getDefaultPool()) WindowedStream(opt->opt_csb, partitions, OPT_compile(tdbb, opt->opt_csb, rse, &deliverStack)); StreamsArray rsbStreams; @@ -1358,8 +1331,8 @@ void WindowSourceNode::getStreams(StreamsArray& list) const { - for (unsigned i = 0; i < windows->nod_count; ++i) - list.add((int)(IPTR) windows->nod_arg[i]->nod_arg[e_part_stream]); + for (const Partition* partition = partitions.begin(); partition != partitions.end(); ++partition) + list.add(partition->stream); } void WindowSourceNode::findDependentFromStreams(const OptimizerRetrieval* optRet, Modified: firebird/trunk/src/jrd/RecordSourceNodes.h =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-25 13:36:24 UTC (rev 51481) +++ firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-25 15:52:46 UTC (rev 51482) @@ -18,6 +18,9 @@ * Adriano dos Santos Fernandes */ +#ifndef JRD_RECORD_SOURCE_NODES_H +#define JRD_RECORD_SOURCE_NODES_H + #include "../jrd/common.h" #include "../common/classes/alloc.h" #include "../common/classes/array.h" @@ -48,7 +51,8 @@ RecordSourceNode(Type aType, MemoryPool& pool) : PermanentStorage(pool), - type(aType) + type(aType), + stream(MAX_USHORT) { } @@ -303,17 +307,31 @@ class WindowSourceNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_WINDOW> { public: + struct Partition + { + Partition() + : stream(MAX_USHORT) + { + } + + USHORT stream; + NestConst<jrd_nod> group; + NestConst<jrd_nod> regroup; + NestConst<jrd_nod> order; + NestConst<jrd_nod> map; + }; + explicit WindowSourceNode(MemoryPool& pool) : TypedNode<RecordSourceNode, RecordSourceNode::TYPE_WINDOW>(pool), rse(NULL), - windows(NULL) + partitions(pool) { } static WindowSourceNode* parse(thread_db* tdbb, CompilerScratch* csb); private: - static jrd_nod* parsePartitionBy(thread_db* tdbb, CompilerScratch* csb); + void parsePartitionBy(thread_db* tdbb, CompilerScratch* csb); public: virtual USHORT getStream() const @@ -344,7 +362,7 @@ private: NestConst<RseNode> rse; - NestConst<jrd_nod> windows; + Firebird::Array<Partition> partitions; }; class RseNode : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RSE> @@ -433,3 +451,5 @@ } //namespace Jrd + +#endif // JRD_RECORD_SOURCE_NODES_H Modified: firebird/trunk/src/jrd/exe.h =================================================================== --- firebird/trunk/src/jrd/exe.h 2010-08-25 13:36:24 UTC (rev 51481) +++ firebird/trunk/src/jrd/exe.h 2010-08-25 15:52:46 UTC (rev 51482) @@ -425,15 +425,6 @@ const int e_extproc_input_assign = 2; const int e_extproc_output_assign = 3; -// Window partition. -const int e_part_group = 0; -const int e_part_regroup = 1; -const int e_part_order = 2; -const int e_part_map = 3; -const int e_part_stream = 4; -const int e_part_count = 4; -const int e_part_length = 5; - // Request resources struct Resource Modified: firebird/trunk/src/jrd/recsrc/RecordSource.h =================================================================== --- firebird/trunk/src/jrd/recsrc/RecordSource.h 2010-08-25 13:36:24 UTC (rev 51481) +++ firebird/trunk/src/jrd/recsrc/RecordSource.h 2010-08-25 15:52:46 UTC (rev 51482) @@ -25,6 +25,7 @@ #include "../common/classes/array.h" #include "../common/classes/NestConst.h" +#include "../jrd/RecordSourceNodes.h" #include "../jrd/req.h" #include "../jrd/rse.h" #include "../jrd/inf_pub.h" @@ -626,7 +627,8 @@ class WindowedStream : public RecordSource { public: - WindowedStream(CompilerScratch* csb, jrd_nod* nodWindows, RecordSource* next); + WindowedStream(CompilerScratch* csb, Firebird::Array<WindowSourceNode::Partition>& partitions, + RecordSource* next); void open(thread_db* tdbb) const; void close(thread_db* tdbb) const; Modified: firebird/trunk/src/jrd/recsrc/WindowedStream.cpp =================================================================== --- firebird/trunk/src/jrd/recsrc/WindowedStream.cpp 2010-08-25 13:36:24 UTC (rev 51481) +++ firebird/trunk/src/jrd/recsrc/WindowedStream.cpp 2010-08-25 15:52:46 UTC (rev 51482) @@ -420,7 +420,8 @@ // ------------------------------ -WindowedStream::WindowedStream(CompilerScratch* csb, jrd_nod* nodWindows, RecordSource* next) +WindowedStream::WindowedStream(CompilerScratch* csb, Array<WindowSourceNode::Partition>& partitions, + RecordSource* next) : m_next(FB_NEW(csb->csb_pool) BufferedStream(csb, next)), m_joinedStream(NULL) { @@ -430,34 +431,30 @@ // Process the unpartioned and unordered map, if existent. - for (unsigned i = 0; i < nodWindows->nod_count; ++i) + for (WindowSourceNode::Partition* partition = partitions.begin(); + partition != partitions.end(); + ++partition) { - jrd_nod* const nodWindow = nodWindows->nod_arg[i]; - jrd_nod* const partition = nodWindow->nod_arg[e_part_group]; - jrd_nod* const partitionMap = nodWindow->nod_arg[e_part_map]; - jrd_nod* const order = nodWindow->nod_arg[e_part_order]; - const USHORT stream = (USHORT)(IPTR) nodWindow->nod_arg[e_part_stream]; - // While here, verify not supported functions/clauses. - const jrd_nod* const* ptr = partitionMap->nod_arg; - for (const jrd_nod* const* const end = ptr + partitionMap->nod_count; ptr < end; ++ptr) + const jrd_nod* const* ptr = partition->map->nod_arg; + for (const jrd_nod* const* const end = ptr + partition->map->nod_count; ptr < end; ++ptr) { const jrd_nod* from = (*ptr)->nod_arg[e_asgn_from]; const AggNode* aggNode = ExprNode::as<AggNode>(from); - if (order && aggNode) + if (partition->order && aggNode) aggNode->checkOrderedWindowCapable(); } - if (!partition && !order) + if (!partition->group && !partition->order) { fb_assert(!m_joinedStream); - m_joinedStream = FB_NEW(csb->csb_pool) AggregatedStream(csb, stream, NULL, - partitionMap, FB_NEW(csb->csb_pool) BufferedStreamWindow(csb, m_next), NULL); + m_joinedStream = FB_NEW(csb->csb_pool) AggregatedStream(csb, partition->stream, NULL, + partition->map, FB_NEW(csb->csb_pool) BufferedStreamWindow(csb, m_next), NULL); - OPT_gen_aggregate_distincts(tdbb, csb, partitionMap); + OPT_gen_aggregate_distincts(tdbb, csb, partition->map); } } @@ -468,14 +465,10 @@ StreamsArray streams; - for (unsigned i = 0; i < nodWindows->nod_count; ++i) + for (WindowSourceNode::Partition* partition = partitions.begin(); + partition != partitions.end(); + ++partition) { - jrd_nod* const nodWindow = nodWindows->nod_arg[i]; - jrd_nod* const partition = nodWindow->nod_arg[e_part_group]; - jrd_nod* const partitionMap = nodWindow->nod_arg[e_part_map]; - jrd_nod* const order = nodWindow->nod_arg[e_part_order]; - const USHORT stream = (USHORT)(IPTR) nodWindow->nod_arg[e_part_stream]; - // Refresh the stream list based on the last m_joinedStream. streams.clear(); m_joinedStream->findUsedStreams(streams); @@ -485,19 +478,19 @@ jrd_nod* partitionOrder; - if (partition) + if (partition->group) { - USHORT orderCount = order ? order->nod_count : 0; - partitionOrder = PAR_make_node(tdbb, (partition->nod_count + orderCount) * 3); + USHORT orderCount = partition->order ? partition->order->nod_count : 0; + partitionOrder = PAR_make_node(tdbb, (partition->group->nod_count + orderCount) * 3); partitionOrder->nod_type = nod_sort; - partitionOrder->nod_count = partition->nod_count + orderCount; + partitionOrder->nod_count = partition->group->nod_count + orderCount; jrd_nod** node1 = partitionOrder->nod_arg; - jrd_nod** node2 = partitionOrder->nod_arg + partition->nod_count + orderCount; - jrd_nod** node3 = node2 + partition->nod_count + orderCount; + jrd_nod** node2 = partitionOrder->nod_arg + partition->group->nod_count + orderCount; + jrd_nod** node3 = node2 + partition->group->nod_count + orderCount; - for (jrd_nod** node = partition->nod_arg; - node != partition->nod_arg + partition->nod_count; + for (jrd_nod** node = partition->group->nod_arg; + node != partition->group->nod_arg + partition->group->nod_count; ++node) { *node1++ = *node; @@ -505,9 +498,11 @@ *node3++ = (jrd_nod*)(IPTR) rse_nulls_default; } - if (order) + if (partition->order) { - for (jrd_nod** node = order->nod_arg; node != order->nod_arg + orderCount; ++node) + for (jrd_nod** node = partition->order->nod_arg; + node != partition->order->nod_arg + orderCount; + ++node) { *node1++ = *node; *node2++ = *(node + orderCount); @@ -516,17 +511,18 @@ } } else - partitionOrder = order; + partitionOrder = partition->order; if (partitionOrder) { SortedStream* sortedStream = OPT_gen_sort(tdbb, csb, streams.begin(), NULL, m_joinedStream, partitionOrder, false); - m_joinedStream = FB_NEW(csb->csb_pool) AggregatedStream(csb, stream, partition, - partitionMap, FB_NEW(csb->csb_pool) BufferedStream(csb, sortedStream), order); + m_joinedStream = FB_NEW(csb->csb_pool) AggregatedStream(csb, partition->stream, + partition->group, partition->map, + FB_NEW(csb->csb_pool) BufferedStream(csb, sortedStream), partition->order); - OPT_gen_aggregate_distincts(tdbb, csb, partitionMap); + OPT_gen_aggregate_distincts(tdbb, csb, partition->map); } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-26 15:40:58
|
Revision: 51487 http://firebird.svn.sourceforge.net/firebird/?rev=51487&view=rev Author: asfernandes Date: 2010-08-26 15:40:51 +0000 (Thu, 26 Aug 2010) Log Message: ----------- Misc Modified Paths: -------------- firebird/trunk/src/jrd/Function.epp firebird/trunk/src/jrd/Function.h firebird/trunk/src/jrd/fun.epp Modified: firebird/trunk/src/jrd/Function.epp =================================================================== --- firebird/trunk/src/jrd/Function.epp 2010-08-26 10:52:11 UTC (rev 51486) +++ firebird/trunk/src/jrd/Function.epp 2010-08-26 15:40:51 UTC (rev 51487) @@ -228,7 +228,7 @@ AutoCacheRequest request_fun(tdbb, irq_l_functions, IRQ_REQUESTS); - fun_repeat temp[MAX_UDF_ARGUMENTS + 1]; + Argument temp[MAX_UDF_ARGUMENTS + 1]; FOR(REQUEST_HANDLE request_fun) X IN RDB$FUNCTIONS @@ -276,7 +276,7 @@ if (Y.RDB$ARGUMENT_POSITION != X.RDB$RETURN_ARGUMENT) function->fun_inputs++; - fun_repeat* const tail = temp + Y.RDB$ARGUMENT_POSITION; + Argument* const tail = temp + Y.RDB$ARGUMENT_POSITION; tail->fun_mechanism = (FUN_T) Y.RDB$MECHANISM; Parameter* const parameter = FB_NEW(*dbb->dbb_permanent) Parameter(*dbb->dbb_permanent); @@ -356,7 +356,7 @@ function->fun_return_arg = X.RDB$RETURN_ARGUMENT; function->fun_temp_length = length; function->fun_args.resize(count + 1); - memcpy(function->fun_args.begin(), temp, function->fun_args.getCount() * sizeof(fun_repeat)); + memcpy(function->fun_args.begin(), temp, function->fun_args.getCount() * sizeof(Argument)); // Prepare the exception message to be used in case this function ever // causes an exception. This is done at this time to save us from preparing @@ -561,7 +561,7 @@ } } -ULONG Function::allocateImpure(CompilerScratch* csb) +ULONG Function::allocateImpure(CompilerScratch* csb) const { const ULONG impure = CMP_impure(csb, sizeof(impure_value)); @@ -668,7 +668,7 @@ jrd_req* const request = tdbb->getRequest(); - const fun_repeat* const return_ptr = &fun_args[fun_return_arg]; + const Argument* const return_ptr = &fun_args[fun_return_arg]; value->vlu_desc = return_ptr->fun_parameter->prm_desc; // If the return data type is any of the string types, Modified: firebird/trunk/src/jrd/Function.h =================================================================== --- firebird/trunk/src/jrd/Function.h 2010-08-26 10:52:11 UTC (rev 51486) +++ firebird/trunk/src/jrd/Function.h 2010-08-26 15:40:51 UTC (rev 51487) @@ -28,18 +28,18 @@ namespace Jrd { - struct fun_repeat - { - NestConst<Parameter> fun_parameter; // parameter info - FUN_T fun_mechanism; // passing mechanism - }; - class Function : public Routine { static const USHORT MAX_ALTER_COUNT = 64; // Number of times an in-cache function can be altered static const char* const EXCEPTION_MESSAGE; public: + struct Argument + { + NestConst<Parameter> fun_parameter; // parameter info + FUN_T fun_mechanism; // passing mechanism + }; + static Function* lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags); static Function* lookup(thread_db* tdbb, const Firebird::QualifiedName& name, bool noscan); @@ -56,7 +56,7 @@ dsc* execute(thread_db* tdbb, const jrd_nod* args, impure_value* value) const; void releaseLocks(thread_db* tdbb); void remove(thread_db* tdbb); - ULONG allocateImpure(CompilerScratch* csb); + ULONG allocateImpure(CompilerScratch* csb) const; void parseBlr(thread_db* tdbb, bid* blob_id, CompilerScratch* csb); jrd_nod* parseArgs(thread_db* tdbb, CompilerScratch* csb); @@ -108,7 +108,7 @@ Format fun_in_msg_format; Format fun_out_msg_format; - Firebird::Array<fun_repeat> fun_args; + Firebird::Array<Argument> fun_args; USHORT fun_flags; // flags USHORT fun_use_count; // requests compiled with function Modified: firebird/trunk/src/jrd/fun.epp =================================================================== --- firebird/trunk/src/jrd/fun.epp 2010-08-26 10:52:11 UTC (rev 51486) +++ firebird/trunk/src/jrd/fun.epp 2010-08-26 15:40:51 UTC (rev 51487) @@ -291,10 +291,10 @@ static SSHORT blob_get_segment(blb*, UCHAR*, USHORT, USHORT*); static void blob_put_segment(blb*, const UCHAR*, USHORT); static SLONG blob_lseek(blb*, USHORT, SLONG); -static SLONG get_scalar_array(const fun_repeat*, DSC*, scalar_array_desc*, UCharStack&); +static SLONG get_scalar_array(const Function::Argument*, DSC*, scalar_array_desc*, UCharStack&); static void invoke(thread_db* tdbb, const Function* function, - const fun_repeat* return_ptr, + const Function::Argument* return_ptr, impure_value* value, UDF_ARG* args, const udf_blob* const return_blob_struct, @@ -330,7 +330,7 @@ SET_TDBB(tdbb); - const fun_repeat* return_ptr = &function->fun_args[function->fun_return_arg]; + const Function::Argument* return_ptr = &function->fun_args[function->fun_return_arg]; jrd_req* request = tdbb->getRequest(); // CVC: restoring the null flag seems like a Borland hack to try to @@ -368,8 +368,8 @@ double d; // Process arguments - const fun_repeat* const end = function->fun_args.end(); - for (const fun_repeat* tail = function->fun_args.begin() + 1; tail < end; ++tail) + const Function::Argument* const end = function->fun_args.end(); + for (const Function::Argument* tail = function->fun_args.begin() + 1; tail < end; ++tail) { DSC* input; if (tail == return_ptr) @@ -805,7 +805,7 @@ } -static SLONG get_scalar_array(const fun_repeat* arg, +static SLONG get_scalar_array(const Function::Argument* arg, DSC* value, scalar_array_desc* scalar_desc, UCharStack& stack) @@ -891,7 +891,7 @@ static void invoke(thread_db* tdbb, const Function* function, - const fun_repeat* return_ptr, + const Function::Argument* return_ptr, impure_value* value, UDF_ARG* args, const udf_blob* const return_blob_struct, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-29 18:26:02
|
Revision: 51500 http://firebird.svn.sourceforge.net/firebird/?rev=51500&view=rev Author: asfernandes Date: 2010-08-29 18:25:55 +0000 (Sun, 29 Aug 2010) Log Message: ----------- Cleanup Modified Paths: -------------- firebird/trunk/src/jrd/exe.cpp firebird/trunk/src/jrd/exe.h firebird/trunk/src/jrd/nod.h Modified: firebird/trunk/src/jrd/exe.cpp =================================================================== --- firebird/trunk/src/jrd/exe.cpp 2010-08-29 18:20:44 UTC (rev 51499) +++ firebird/trunk/src/jrd/exe.cpp 2010-08-29 18:25:55 UTC (rev 51500) @@ -2571,11 +2571,6 @@ } break; - case nod_nop: - request->req_operation = jrd_req::req_return; - node = node->nod_parent; - break; - case nod_receive: node = receive_msg(tdbb, node); break; Modified: firebird/trunk/src/jrd/exe.h =================================================================== --- firebird/trunk/src/jrd/exe.h 2010-08-29 18:20:44 UTC (rev 51499) +++ firebird/trunk/src/jrd/exe.h 2010-08-29 18:25:55 UTC (rev 51500) @@ -107,17 +107,6 @@ class jrd_nod : public jrd_node_base { public: -/* jrd_nod() - : nod_parent(0), - nod_impure(0), - nod_type(nod_nop), - nod_flags(0), - nod_scale(0), - nod_count(0) - { - nod_arg[0] = 0; - }*/ - jrd_nod* nod_arg[1]; // Replace the line above by this block to check deep const-correctness. Modified: firebird/trunk/src/jrd/nod.h =================================================================== --- firebird/trunk/src/jrd/nod.h 2010-08-29 18:20:44 UTC (rev 51499) +++ firebird/trunk/src/jrd/nod.h 2010-08-29 18:25:55 UTC (rev 51500) @@ -96,7 +96,6 @@ NODE(nod_block, block, "") NODE(nod_error_handler, error_handler, "") NODE(nod_cast, cast, "CAST") - NODE(nod_nop, nop, "") NODE(nod_start_savepoint, start_savepoint, "") NODE(nod_end_savepoint, end_savepoint, "") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-08-31 00:20:40
|
Revision: 51505 http://firebird.svn.sourceforge.net/firebird/?rev=51505&view=rev Author: asfernandes Date: 2010-08-31 00:20:33 +0000 (Tue, 31 Aug 2010) Log Message: ----------- Refactor nod_index and nod_bit_* to InversionNode Modified Paths: -------------- firebird/trunk/src/jrd/Optimizer.cpp firebird/trunk/src/jrd/Optimizer.h firebird/trunk/src/jrd/RecordSourceNodes.h firebird/trunk/src/jrd/evl.cpp firebird/trunk/src/jrd/evl_proto.h firebird/trunk/src/jrd/exe.h firebird/trunk/src/jrd/nod.h firebird/trunk/src/jrd/opt.cpp firebird/trunk/src/jrd/recsrc/BitmapTableScan.cpp firebird/trunk/src/jrd/recsrc/IndexTableScan.cpp firebird/trunk/src/jrd/recsrc/RecordSource.cpp firebird/trunk/src/jrd/recsrc/RecordSource.h Modified: firebird/trunk/src/jrd/Optimizer.cpp =================================================================== --- firebird/trunk/src/jrd/Optimizer.cpp 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/Optimizer.cpp 2010-08-31 00:20:33 UTC (rev 51505) @@ -899,8 +899,8 @@ } } -jrd_nod* OptimizerRetrieval::composeInversion(jrd_nod* node1, jrd_nod* node2, - nod_t node_type) const +InversionNode* OptimizerRetrieval::composeInversion(InversionNode* node1, InversionNode* node2, + InversionNode::Type node_type) const { /************************************** * @@ -914,33 +914,29 @@ * **************************************/ - if (!node2) { + if (!node2) return node1; - } - if (!node1) { + if (!node1) return node2; - } - if (node_type == nod_bit_or) + if (node_type == InversionNode::TYPE_OR) { - if ((node1->nod_type == nod_index) && - (node2->nod_type == nod_index) && - (reinterpret_cast<IndexRetrieval*>(node1->nod_arg[e_idx_retrieval])->irb_index == - reinterpret_cast<IndexRetrieval*>(node2->nod_arg[e_idx_retrieval])->irb_index)) + if (node1->type == InversionNode::TYPE_INDEX && + node2->type == InversionNode::TYPE_INDEX && + node1->retrieval->irb_index == node2->retrieval->irb_index) { - node_type = nod_bit_in; + node_type = InversionNode::TYPE_IN; } - else if ((node1->nod_type == nod_bit_in) && - (node2->nod_type == nod_index) && - (reinterpret_cast<IndexRetrieval*>(node1->nod_arg[1]->nod_arg[e_idx_retrieval])->irb_index == - reinterpret_cast<IndexRetrieval*>(node2->nod_arg[e_idx_retrieval])->irb_index)) + else if (node1->type == InversionNode::TYPE_IN && + node2->type == InversionNode::TYPE_INDEX && + node1->node2->retrieval->irb_index == node2->retrieval->irb_index) { - node_type = nod_bit_in; + node_type = InversionNode::TYPE_IN; } } - return OPT_make_binary_node(node_type, node1, node2, false); + return FB_NEW(pool) InversionNode(node_type, node1, node2); } @@ -1371,7 +1367,7 @@ idx->idx_runtime_flags |= idx_navigate; indexScratches[i].utilized = true; - jrd_nod* const index_node = makeIndexScanNode(&indexScratches[i]); + InversionNode* const index_node = makeIndexScanNode(&indexScratches[i]); const USHORT key_length = ROUNDUP(BTR_key_length(tdbb, relation, idx), sizeof(SLONG)); return FB_NEW(*tdbb->getDefaultPool()) IndexTableScan(csb, getAlias(), stream, index_node, key_length); @@ -1638,7 +1634,7 @@ } -jrd_nod* OptimizerRetrieval::makeIndexNode(const index_desc* idx) const +InversionNode* OptimizerRetrieval::makeIndexNode(const index_desc* idx) const { /************************************** * @@ -1661,21 +1657,19 @@ Resource::rsc_index, idx->idx_id); } - jrd_nod* node = PAR_make_node(tdbb, e_idx_length); - node->nod_type = nod_index; - node->nod_count = 0; - IndexRetrieval* retrieval = FB_NEW_RPT(pool, idx->idx_count * 2) IndexRetrieval(); - node->nod_arg[e_idx_retrieval] = (jrd_nod*) retrieval; retrieval->irb_index = idx->idx_id; memcpy(&retrieval->irb_desc, idx, sizeof(retrieval->irb_desc)); - if (csb) { - node->nod_impure = CMP_impure(csb, sizeof(impure_inversion)); - } + + InversionNode* node = FB_NEW(pool) InversionNode(retrieval); + + if (csb) + node->impure = CMP_impure(csb, sizeof(impure_inversion)); + return node; } -jrd_nod* OptimizerRetrieval::makeIndexScanNode(IndexScratch* indexScratch) const +InversionNode* OptimizerRetrieval::makeIndexScanNode(IndexScratch* indexScratch) const { /************************************** * @@ -1688,14 +1682,13 @@ * **************************************/ - if (!createIndexScanNodes) { + if (!createIndexScanNodes) return NULL; - } // Allocate both a index retrieval node and block. index_desc* idx = indexScratch->idx; - jrd_nod* node = makeIndexNode(idx); - IndexRetrieval* retrieval = (IndexRetrieval*) node->nod_arg[e_idx_retrieval]; + InversionNode* node = makeIndexNode(idx); + IndexRetrieval* retrieval = node->retrieval; retrieval->irb_relation = relation; // Pick up lower bound segment values @@ -1717,6 +1710,7 @@ int i = 0; bool ignoreNullsOnScan = true; IndexScratchSegment** segment = indexScratch->segments.begin(); + for (i = 0; i < MAX(indexScratch->lowerCount, indexScratch->upperCount); i++) { if (segment[i]->scanType == segmentScanMissing) @@ -1728,19 +1722,19 @@ } else { - if (i < indexScratch->lowerCount) { + if (i < indexScratch->lowerCount) *lower++ = segment[i]->lowerValue; - } - if (i < indexScratch->upperCount) { + + if (i < indexScratch->upperCount) *upper++ = segment[i]->upperValue; - } - if (segment[i]->scanType == segmentScanEquivalent) { + + if (segment[i]->scanType == segmentScanEquivalent) ignoreNullsOnScan = false; - } } } i = MAX(indexScratch->lowerCount, indexScratch->upperCount) - 1; + if (i >= 0) { if (segment[i]->scanType == segmentScanStarting) @@ -1796,15 +1790,14 @@ // which requires NULLs to be found in the index. // A second exception is when this index is used for navigation. if (ignoreNullsOnScan && !(idx->idx_runtime_flags & idx_navigate)) - { retrieval->irb_generic |= irb_ignore_null_value_key; - } // Check to see if this is really an equality retrieval if (retrieval->irb_lower_count == retrieval->irb_upper_count) { retrieval->irb_generic |= irb_equality; segment = indexScratch->segments.begin(); + for (i = 0; i < retrieval->irb_lower_count; i++) { if (segment[i]->lowerValue != segment[i]->upperValue) @@ -1818,15 +1811,13 @@ // If we are matching less than the full index, this is a partial match if (idx->idx_flags & idx_descending) { - if (retrieval->irb_lower_count < idx->idx_count) { + if (retrieval->irb_lower_count < idx->idx_count) retrieval->irb_generic |= irb_partial; - } } else { - if (retrieval->irb_upper_count < idx->idx_count) { + if (retrieval->irb_upper_count < idx->idx_count) retrieval->irb_generic |= irb_partial; - } } // mark the index as utilized for the purposes of this compile @@ -1916,15 +1907,14 @@ // we can make the inversion and return it. if (currentInv->unique && currentInv->dependencies) { - if (!invCandidate) { + if (!invCandidate) invCandidate = FB_NEW(pool) InversionCandidate(pool); - } - if (!currentInv->inversion && currentInv->scratch) { + + if (!currentInv->inversion && currentInv->scratch) invCandidate->inversion = makeIndexScanNode(currentInv->scratch); - } - else { + else invCandidate->inversion = currentInv->inversion; - } + invCandidate->unique = currentInv->unique; invCandidate->selectivity = currentInv->selectivity; invCandidate->cost = currentInv->cost; @@ -2156,13 +2146,14 @@ if (!bestCandidate->inversion && bestCandidate->scratch) { invCandidate->inversion = composeInversion(invCandidate->inversion, - makeIndexScanNode(bestCandidate->scratch), nod_bit_and); + makeIndexScanNode(bestCandidate->scratch), InversionNode::TYPE_AND); } else { invCandidate->inversion = composeInversion(invCandidate->inversion, - bestCandidate->inversion, nod_bit_and); + bestCandidate->inversion, InversionNode::TYPE_AND); } + invCandidate->unique = (invCandidate->unique || bestCandidate->unique); invCandidate->selectivity = totalSelectivity; invCandidate->cost += bestCandidate->cost; @@ -2171,19 +2162,20 @@ invCandidate->matchedSegments = MAX(bestCandidate->matchedSegments, invCandidate->matchedSegments); invCandidate->dependencies += bestCandidate->dependencies; + for (size_t j = 0; j < bestCandidate->matches.getCount(); j++) { - if (!matches.exist(bestCandidate->matches[j])) { + if (!matches.exist(bestCandidate->matches[j])) matches.add(bestCandidate->matches[j]); - } } + if (bestCandidate->boolean) { - if (!matches.exist(bestCandidate->boolean)) { + if (!matches.exist(bestCandidate->boolean)) matches.add(bestCandidate->boolean); - } } } + if (invCandidate->unique) { // Single unique full equal match is enough @@ -2554,12 +2546,8 @@ if (createIndexScanNodes) { - jrd_nod* const inversion = PAR_make_node(tdbb, 2); - inversion->nod_count = 1; - inversion->nod_type = nod_bit_dbkey; - inversion->nod_arg[0] = value; - inversion->nod_arg[1] = (jrd_nod*)(IPTR) n; - inversion->nod_impure = CMP_impure(csb, sizeof(impure_inversion)); + InversionNode* const inversion = FB_NEW(pool) InversionNode(value, n); + inversion->impure = CMP_impure(csb, sizeof(impure_inversion)); invCandidate->inversion = inversion; } @@ -2645,8 +2633,8 @@ if (invCandidate2) { InversionCandidate* invCandidate = FB_NEW(pool) InversionCandidate(pool); - invCandidate->inversion = - composeInversion(invCandidate1->inversion, invCandidate2->inversion, nod_bit_or); + invCandidate->inversion = composeInversion(invCandidate1->inversion, + invCandidate2->inversion, InversionNode::TYPE_OR); invCandidate->unique = (invCandidate1->unique && invCandidate2->unique); invCandidate->selectivity = invCandidate1->selectivity + invCandidate2->selectivity; invCandidate->cost = invCandidate1->cost + invCandidate2->cost; Modified: firebird/trunk/src/jrd/Optimizer.h =================================================================== --- firebird/trunk/src/jrd/Optimizer.h 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/Optimizer.h 2010-08-31 00:20:33 UTC (rev 51505) @@ -38,6 +38,7 @@ #include "../common/classes/alloc.h" #include "../common/classes/array.h" +#include "../jrd/RecordSourceNodes.h" #include "../jrd/rse.h" #include "../jrd/exe.h" @@ -69,6 +70,7 @@ class OptimizerBlk; class jrd_rel; class IndexTableScan; +class InversionNode; class PlanNode; class River; class SortNode; @@ -140,7 +142,7 @@ int indexes; int dependencies; jrd_nod* boolean; - jrd_nod* inversion; + InversionNode* inversion; IndexScratch* scratch; bool used; bool unique; @@ -165,14 +167,15 @@ void findDependentFromStreams(jrd_nod* node, SortedStreamList* streamList) const; protected: - jrd_nod* composeInversion(jrd_nod* node1, jrd_nod* node2, nod_t node_type) const; + InversionNode* composeInversion(InversionNode* node1, InversionNode* node2, + InversionNode::Type node_type) const; const Firebird::string& getAlias(); InversionCandidate* generateInversion(IndexTableScan** rsb); IndexTableScan* generateNavigation(); void getInversionCandidates(InversionCandidateList* inversions, IndexScratchList* indexScratches, USHORT scope) const; - jrd_nod* makeIndexNode(const index_desc* idx) const; - jrd_nod* makeIndexScanNode(IndexScratch* indexScratch) const; + InversionNode* makeIndexNode(const index_desc* idx) const; + InversionNode* makeIndexScanNode(IndexScratch* indexScratch) const; InversionCandidate* makeInversion(InversionCandidateList* inversions) const; bool matchBoolean(IndexScratch* indexScratch, jrd_nod* boolean, USHORT scope) const; InversionCandidate* matchDbKey(jrd_nod* boolean) const; Modified: firebird/trunk/src/jrd/RecordSourceNodes.h =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/RecordSourceNodes.h 2010-08-31 00:20:33 UTC (rev 51505) @@ -32,6 +32,7 @@ namespace Jrd { +class IndexRetrieval; class OptimizerRetrieval; class ProcedureScan; class RelationSourceNode; @@ -137,7 +138,61 @@ Firebird::Array<NestConst<PlanNode> > subNodes; }; +class InversionNode +{ +public: + enum Type + { + TYPE_AND, + TYPE_OR, + TYPE_IN, + TYPE_DBKEY, + TYPE_INDEX + }; + InversionNode(Type aType, InversionNode* aNode1, InversionNode* aNode2) + : type(aType), + impure(0), + retrieval(NULL), + node1(aNode1), + node2(aNode2), + value(NULL), + id(0) + { + } + + InversionNode(IndexRetrieval* aRetrieval) + : type(TYPE_INDEX), + impure(0), + retrieval(aRetrieval), + node1(NULL), + node2(NULL), + value(NULL), + id(0) + { + } + + InversionNode(jrd_nod* aValue, USHORT aId) + : type(TYPE_DBKEY), + impure(0), + retrieval(NULL), + node1(NULL), + node2(NULL), + value(aValue), + id(aId) + { + } + + Type type; + ULONG impure; + NestConst<IndexRetrieval> retrieval; + NestConst<InversionNode> node1; + NestConst<InversionNode> node2; + NestConst<jrd_nod> value; + USHORT id; +}; + + class RecordSourceNode : public Firebird::PermanentStorage { public: Modified: firebird/trunk/src/jrd/evl.cpp =================================================================== --- firebird/trunk/src/jrd/evl.cpp 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/evl.cpp 2010-08-31 00:20:33 UTC (rev 51505) @@ -254,7 +254,7 @@ } -RecordBitmap** EVL_bitmap(thread_db* tdbb, const jrd_nod* node, RecordBitmap* bitmap_and) +RecordBitmap** EVL_bitmap(thread_db* tdbb, const InversionNode* node, RecordBitmap* bitmap_and) { /************************************** * @@ -274,42 +274,40 @@ if (--tdbb->tdbb_quantum < 0) JRD_reschedule(tdbb, 0, true); - switch (node->nod_type) + switch (node->type) { - case nod_bit_and: + case InversionNode::TYPE_AND: { - RecordBitmap** bitmap = EVL_bitmap(tdbb, node->nod_arg[0], bitmap_and); + RecordBitmap** bitmap = EVL_bitmap(tdbb, node->node1, bitmap_and); if (!(*bitmap) || !(*bitmap)->getFirst()) return bitmap; - return EVL_bitmap(tdbb, node->nod_arg[1], *bitmap); + return EVL_bitmap(tdbb, node->node2, *bitmap); } - case nod_bit_or: + case InversionNode::TYPE_OR: return RecordBitmap::bit_or( - EVL_bitmap(tdbb, node->nod_arg[0], bitmap_and), - EVL_bitmap(tdbb, node->nod_arg[1], bitmap_and)); + EVL_bitmap(tdbb, node->node1, bitmap_and), + EVL_bitmap(tdbb, node->node2, bitmap_and)); - case nod_bit_in: + case InversionNode::TYPE_IN: { - RecordBitmap** inv_bitmap = EVL_bitmap(tdbb, node->nod_arg[0], bitmap_and); - BTR_evaluate(tdbb, - reinterpret_cast<const IndexRetrieval*>(node->nod_arg[1]->nod_arg[e_idx_retrieval]), - inv_bitmap, bitmap_and); + RecordBitmap** inv_bitmap = EVL_bitmap(tdbb, node->node1, bitmap_and); + BTR_evaluate(tdbb, node->node2->retrieval, inv_bitmap, bitmap_and); return inv_bitmap; } - case nod_bit_dbkey: + case InversionNode::TYPE_DBKEY: { - impure_inversion* impure = tdbb->getRequest()->getImpure<impure_inversion>(node->nod_impure); + impure_inversion* impure = tdbb->getRequest()->getImpure<impure_inversion>(node->impure); RecordBitmap::reset(impure->inv_bitmap); - const dsc* desc = EVL_expr(tdbb, node->nod_arg[0]); + const dsc* desc = EVL_expr(tdbb, node->value); if (!(tdbb->getRequest()->req_flags & req_null) && desc->dsc_length == sizeof(RecordNumber::Packed)) { - const USHORT id = (USHORT)(IPTR) node->nod_arg[1]; - Firebird::Aligner<RecordNumber::Packed> alignedNumbers(desc->dsc_address, desc->dsc_length); + const USHORT id = node->id; + Aligner<RecordNumber::Packed> alignedNumbers(desc->dsc_address, desc->dsc_length); const RecordNumber::Packed* numbers = alignedNumbers; RecordNumber rel_dbkey; rel_dbkey.bid_decode(&numbers[id]); @@ -323,18 +321,18 @@ return &impure->inv_bitmap; } - case nod_index: + case InversionNode::TYPE_INDEX: { - impure_inversion* impure = tdbb->getRequest()->getImpure<impure_inversion>(node->nod_impure); + impure_inversion* impure = tdbb->getRequest()->getImpure<impure_inversion>(node->impure); RecordBitmap::reset(impure->inv_bitmap); - BTR_evaluate(tdbb, reinterpret_cast<const IndexRetrieval*>(node->nod_arg[e_idx_retrieval]), - &impure->inv_bitmap, bitmap_and); + BTR_evaluate(tdbb, node->retrieval, &impure->inv_bitmap, bitmap_and); return &impure->inv_bitmap; } default: BUGCHECK(230); // msg 230 EVL_bitmap: invalid operation } + return NULL; } Modified: firebird/trunk/src/jrd/evl_proto.h =================================================================== --- firebird/trunk/src/jrd/evl_proto.h 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/evl_proto.h 2010-08-31 00:20:33 UTC (rev 51505) @@ -28,6 +28,7 @@ namespace Jrd { + class InversionNode; struct Item; struct ItemInfo; } @@ -36,7 +37,7 @@ dsc* EVL_add(const dsc*, const Jrd::jrd_nod*, Jrd::impure_value*); dsc* EVL_add2(const dsc*, const Jrd::jrd_nod*, Jrd::impure_value*); dsc* EVL_assign_to(Jrd::thread_db* tdbb, const Jrd::jrd_nod*); -Jrd::RecordBitmap** EVL_bitmap(Jrd::thread_db* tdbb, const Jrd::jrd_nod*, Jrd::RecordBitmap*); +Jrd::RecordBitmap** EVL_bitmap(Jrd::thread_db* tdbb, const Jrd::InversionNode*, Jrd::RecordBitmap*); bool EVL_boolean(Jrd::thread_db* tdbb, const Jrd::jrd_nod*); dsc* EVL_expr(Jrd::thread_db* tdbb, const Jrd::jrd_nod*); bool EVL_field(Jrd::jrd_rel*, Jrd::Record*, USHORT, dsc*); Modified: firebird/trunk/src/jrd/exe.h =================================================================== --- firebird/trunk/src/jrd/exe.h 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/exe.h 2010-08-31 00:20:33 UTC (rev 51505) @@ -245,9 +245,6 @@ const int e_asgn_missing2 = 3; // Value for substitute for missing const int e_asgn_length = 4; -const int e_idx_retrieval = 0; -const int e_idx_length = 1; - const int e_lbl_statement = 0; const int e_lbl_label = 1; const int e_lbl_length = 2; Modified: firebird/trunk/src/jrd/nod.h =================================================================== --- firebird/trunk/src/jrd/nod.h 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/nod.h 2010-08-31 00:20:33 UTC (rev 51505) @@ -48,11 +48,6 @@ NODE(nod_divide, divide, " / ") NODE(nod_field, field, "") NODE(nod_from, from, "") - NODE(nod_index, index, "") - NODE(nod_bit_and, bit_and, "") - NODE(nod_bit_or, bit_or, "") - NODE(nod_bit_in, bit_in, "") - NODE(nod_bit_dbkey, bit_dbkey, "") NODE(nod_literal, literal, "") NODE(nod_max, max, "MAX") NODE(nod_min, min, "MIN") Modified: firebird/trunk/src/jrd/opt.cpp =================================================================== --- firebird/trunk/src/jrd/opt.cpp 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/opt.cpp 2010-08-31 00:20:33 UTC (rev 51505) @@ -2573,7 +2573,7 @@ RecordSource* rsb = NULL; IndexTableScan* nav_rsb = NULL; - jrd_nod* inversion = NULL; + InversionNode* inversion = NULL; if (relation->rel_file) { @@ -2600,9 +2600,7 @@ AutoPtr<InversionCandidate> candidate(optimizerRetrieval.getInversion(&nav_rsb)); if (candidate && candidate->inversion) - { inversion = candidate->inversion; - } } if (outer_flag) @@ -2613,9 +2611,11 @@ // boolean and mark it used. *return_boolean = NULL; opt_end = opt->opt_conjuncts.begin() + opt->opt_base_conjuncts; + for (tail = opt->opt_conjuncts.begin(); tail < opt_end; tail++) { jrd_nod* node = tail->opt_conjunct_node; + if (!(tail->opt_conjunct_flags & opt_conjunct_used) && OPT_computable(csb, node, -1, false, false)) { Modified: firebird/trunk/src/jrd/recsrc/BitmapTableScan.cpp =================================================================== --- firebird/trunk/src/jrd/recsrc/BitmapTableScan.cpp 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/recsrc/BitmapTableScan.cpp 2010-08-31 00:20:33 UTC (rev 51505) @@ -36,7 +36,7 @@ // --------------------------------------------- BitmapTableScan::BitmapTableScan(CompilerScratch* csb, const string& name, UCHAR stream, - jrd_nod* inversion) + InversionNode* inversion) : RecordStream(csb, stream), m_name(csb->csb_pool, name), m_inversion(inversion) { fb_assert(m_inversion); Modified: firebird/trunk/src/jrd/recsrc/IndexTableScan.cpp =================================================================== --- firebird/trunk/src/jrd/recsrc/IndexTableScan.cpp 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/recsrc/IndexTableScan.cpp 2010-08-31 00:20:33 UTC (rev 51505) @@ -42,7 +42,7 @@ // ------------------------------------ IndexTableScan::IndexTableScan(CompilerScratch* csb, const string& name, UCHAR stream, - jrd_nod* index, USHORT length) + InversionNode* index, USHORT length) : RecordStream(csb, stream), m_name(csb->csb_pool, name), m_index(index), m_inversion(NULL), m_length(length), m_offset(0) { @@ -139,7 +139,7 @@ temporary_key key; memcpy(key.key_data, impure->irsb_nav_data, impure->irsb_nav_length); - IndexRetrieval* const retrieval = (IndexRetrieval*) m_index->nod_arg[e_idx_retrieval]; + const IndexRetrieval* const retrieval = m_index->retrieval; // set the upper (or lower) limit for navigational retrieval temporary_key upper; @@ -489,7 +489,7 @@ impure->irsb_nav_length = 0; // Find the starting leaf page - IndexRetrieval* const retrieval = (IndexRetrieval*) m_index->nod_arg[e_idx_retrieval]; + const IndexRetrieval* const retrieval = m_index->retrieval; index_desc* const idx = (index_desc*) ((SCHAR*) impure + m_offset); temporary_key lower, upper; Ods::btree_page* page = BTR_find_page(tdbb, retrieval, window, idx, &lower, &upper); Modified: firebird/trunk/src/jrd/recsrc/RecordSource.cpp =================================================================== --- firebird/trunk/src/jrd/recsrc/RecordSource.cpp 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/recsrc/RecordSource.cpp 2010-08-31 00:20:33 UTC (rev 51505) @@ -70,39 +70,38 @@ buffer.add(namePtr, nameLength); } -void RecordSource::dumpInversion(thread_db* tdbb, const jrd_nod* inversion, UCharBuffer& buffer) +void RecordSource::dumpInversion(thread_db* tdbb, const InversionNode* inversion, UCharBuffer& buffer) { // spit out the node type - switch (inversion->nod_type) + switch (inversion->type) { - case nod_bit_and: + case InversionNode::TYPE_AND: buffer.add(isc_info_rsb_and); break; - case nod_bit_or: - case nod_bit_in: + case InversionNode::TYPE_OR: + case InversionNode::TYPE_IN: buffer.add(isc_info_rsb_or); break; - case nod_bit_dbkey: + case InversionNode::TYPE_DBKEY: buffer.add(isc_info_rsb_dbkey); break; - case nod_index: + case InversionNode::TYPE_INDEX: buffer.add(isc_info_rsb_index); break; } // dump sub-nodes or the actual index info - switch (inversion->nod_type) + switch (inversion->type) { - case nod_bit_and: - case nod_bit_or: - case nod_bit_in: - dumpInversion(tdbb, inversion->nod_arg[0], buffer); - dumpInversion(tdbb, inversion->nod_arg[1], buffer); + case InversionNode::TYPE_AND: + case InversionNode::TYPE_OR: + case InversionNode::TYPE_IN: + dumpInversion(tdbb, inversion->node1, buffer); + dumpInversion(tdbb, inversion->node2, buffer); break; - case nod_index: + case InversionNode::TYPE_INDEX: { - const IndexRetrieval* const retrieval = - (IndexRetrieval*) inversion->nod_arg[e_idx_retrieval]; + const IndexRetrieval* const retrieval = inversion->retrieval; Firebird::MetaName indexName; MET_lookup_index(tdbb, indexName, retrieval->irb_relation->rel_name, Modified: firebird/trunk/src/jrd/recsrc/RecordSource.h =================================================================== --- firebird/trunk/src/jrd/recsrc/RecordSource.h 2010-08-31 00:12:20 UTC (rev 51504) +++ firebird/trunk/src/jrd/recsrc/RecordSource.h 2010-08-31 00:20:33 UTC (rev 51505) @@ -97,7 +97,7 @@ static void dumpName(thread_db* tdbb, const Firebird::string& name, Firebird::UCharBuffer& buffer); - static void dumpInversion(thread_db* tdbb, const jrd_nod* inversion, + static void dumpInversion(thread_db* tdbb, const InversionNode* inversion, Firebird::UCharBuffer& buffer); static void saveRecord(thread_db* tdbb, record_param* rpb); @@ -159,7 +159,7 @@ public: BitmapTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream, - jrd_nod* inversion); + InversionNode* inversion); void open(thread_db* tdbb) const; void close(thread_db* tdbb) const; @@ -170,7 +170,7 @@ private: const Firebird::string m_name; - NestConst<jrd_nod> const m_inversion; + NestConst<InversionNode> const m_inversion; }; class IndexTableScan : public RecordStream @@ -192,7 +192,7 @@ public: IndexTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream, - jrd_nod* index, USHORT keyLength); + InversionNode* index, USHORT keyLength); void open(thread_db* tdbb) const; void close(thread_db* tdbb) const; @@ -201,7 +201,7 @@ void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const; - void setInversion(jrd_nod* inversion) + void setInversion(InversionNode* inversion) { fb_assert(!m_inversion); m_inversion = inversion; @@ -218,8 +218,8 @@ bool setupBitmaps(thread_db* tdbb, Impure* impure) const; const Firebird::string m_name; - NestConst<jrd_nod> const m_index; - NestConst<jrd_nod> m_inversion; + NestConst<InversionNode> const m_index; + NestConst<InversionNode> m_inversion; const size_t m_length; size_t m_offset; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-09-20 16:26:32
|
Revision: 51580 http://firebird.svn.sourceforge.net/firebird/?rev=51580&view=rev Author: asfernandes Date: 2010-09-20 16:26:25 +0000 (Mon, 20 Sep 2010) Log Message: ----------- Misc Modified Paths: -------------- firebird/trunk/src/jrd/cmp.cpp firebird/trunk/src/jrd/nod.h Modified: firebird/trunk/src/jrd/cmp.cpp =================================================================== --- firebird/trunk/src/jrd/cmp.cpp 2010-09-20 16:07:50 UTC (rev 51579) +++ firebird/trunk/src/jrd/cmp.cpp 2010-09-20 16:26:25 UTC (rev 51580) @@ -1253,11 +1253,6 @@ } return node; - case nod_for: - ///args = e_for_length; - fb_assert(false); - break; - case nod_argument: if (remapArgument()) return input; Modified: firebird/trunk/src/jrd/nod.h =================================================================== --- firebird/trunk/src/jrd/nod.h 2010-09-20 16:07:50 UTC (rev 51579) +++ firebird/trunk/src/jrd/nod.h 2010-09-20 16:26:25 UTC (rev 51580) @@ -24,83 +24,72 @@ */ NODE(nod_asn_list, asn_list, "") - NODE(nod_assignment, assignment, "") - NODE(nod_dcl_variable, declare, "") - NODE(nod_erase, erase, "") - NODE(nod_for, for, "") - NODE(nod_handler, handler, "") - NODE(nod_label, label, "") - NODE(nod_leave, leave, "") - NODE(nod_list, list, "") - NODE(nod_loop, loop, "") - NODE(nod_message, message, "") - NODE(nod_modify, modify, "") - NODE(nod_receive, receive, "") - NODE(nod_select, select, "") - NODE(nod_store, store, "") +NODE(nod_validate, validate, "") - NODE(nod_argument, argument, "") - NODE(nod_variable, variable, "") - NODE(nod_average, average, "AVG") - NODE(nod_count, count, "COUNT") - NODE(nod_dbkey, dbkey, "ROWID") - NODE(nod_field, field, "") - NODE(nod_from, from, "") - NODE(nod_literal, literal, "") - NODE(nod_max, max, "MAX") - NODE(nod_min, min, "MIN") - NODE(nod_scalar, scalar, "") - NODE(nod_gen_id, recnum, "") - NODE(nod_prot_mask, prot_mask, "") - NODE(nod_upcase, upcase, "UPPER") - NODE(nod_lock_state, lock_state, "") - NODE(nod_null, null, "NULL") - NODE(nod_substr, substr, "") - NODE(nod_total, total, "SUM") - NODE(nod_trim, trim, "") - NODE(nod_validate, validate, "") +NODE(nod_assignment, assignment, "") +NODE(nod_dcl_variable, declare, "") +NODE(nod_erase, erase, "") +NODE(nod_handler, handler, "") +NODE(nod_label, label, "") +NODE(nod_leave, leave, "") +NODE(nod_list, list, "") +NODE(nod_loop, loop, "") +NODE(nod_message, message, "") +NODE(nod_modify, modify, "") +NODE(nod_receive, receive, "") +NODE(nod_select, select, "") +NODE(nod_store, store, "") +NODE(nod_exec_proc, exec_proc, "") +NODE(nod_block, block, "") +NODE(nod_error_handler, error_handler, "") +NODE(nod_start_savepoint, start_savepoint, "") +NODE(nod_end_savepoint, end_savepoint, "") +NODE(nod_stall, stall, "SERVER STALL") +NODE(nod_exec_sql, exec_sql, "EXECUTE STATEMENT") +NODE(nod_exec_into, exec_sql_into, "EXECUTE VARCHAR INTO") +NODE(nod_exec_stmt, exec_stmt, "EXECUTE STATEMENT") +NODE(nod_dcl_cursor, declare_cursor, "DECLARE CURSOR") +NODE(nod_cursor_stmt, cursor_stmt, "CURSOR STATEMENT") +NODE(nod_continue_loop, continue_loop, "") - NODE(nod_exec_proc, exec_proc, "") - NODE(nod_block, block, "") - NODE(nod_error_handler, error_handler, "") - NODE(nod_cast, cast, "CAST") - NODE(nod_start_savepoint, start_savepoint, "") - NODE(nod_end_savepoint, end_savepoint, "") +NODE(nod_set_generator, set_generator, "") +NODE(nod_set_generator2, set_generator, "") - NODE(nod_set_generator, set_generator, "") +NODE(nod_argument, argument, "") +NODE(nod_variable, variable, "") +NODE(nod_dbkey, dbkey, "ROWID") +NODE(nod_field, field, "") +NODE(nod_from, from, "") +NODE(nod_literal, literal, "") +NODE(nod_scalar, scalar, "") +NODE(nod_gen_id, recnum, "") +NODE(nod_prot_mask, prot_mask, "") +NODE(nod_upcase, upcase, "UPPER") +NODE(nod_lock_state, lock_state, "") +NODE(nod_null, null, "NULL") +NODE(nod_substr, substr, "") +NODE(nod_trim, trim, "") +NODE(nod_cast, cast, "CAST") +NODE(nod_rec_version, record_version, "RECORD VERSION") +NODE(nod_extract, extract, "EXTRACT") +NODE(nod_gen_id2, recnum, "") +NODE(nod_lowcase, lowcase, "LOWER") +NODE(nod_strlen, strlen, "STRLEN") +NODE(nod_src_info, source_info, "") +NODE(nod_init_variable, init_variable, "") +NODE(nod_domain_validation, domain_validation, "") +NODE(nod_derived_expr, derived_expr, "derived_expr") -/* Required for NULL handling */ +NODE(nod_stmt_expr, stmt_expr, "stmt_expr") - NODE(nod_rec_version, record_version, "RECORD VERSION") - NODE(nod_stall, stall, "SERVER STALL") +NODE(nod_average, average, "AVG") +NODE(nod_count, count, "COUNT") +NODE(nod_max, max, "MAX") +NODE(nod_min, min, "MIN") +NODE(nod_total, total, "SUM") +NODE(nod_average2, average2, "AVG") +NODE(nod_total2, total, "SUM") -/* Improved date handling */ - NODE(nod_extract, extract, "EXTRACT") - - NODE(nod_average2, average2, "AVG") - NODE(nod_gen_id2, recnum, "") - NODE(nod_set_generator2, set_generator, "") - NODE(nod_total2, total, "SUM") - -/* EXECUTE STATEMENT */ - NODE(nod_exec_sql, exec_sql, "EXECUTE STATEMENT") - -/* EXECUTE VARCHAR INTO ...*/ - NODE(nod_exec_into, exec_sql_into, "EXECUTE VARCHAR INTO") - NODE(nod_exec_stmt, exec_stmt, "EXECUTE STATEMENT") - - NODE(nod_dcl_cursor, declare_cursor, "DECLARE CURSOR") - NODE(nod_cursor_stmt, cursor_stmt, "CURSOR STATEMENT") - NODE(nod_lowcase, lowcase, "LOWER") - - NODE(nod_strlen, strlen, "STRLEN") - - NODE(nod_src_info, source_info, "") - NODE(nod_init_variable, init_variable, "") - NODE(nod_domain_validation, domain_validation, "") - NODE(nod_class_exprnode_jrd, class_exprnode_jrd, "class_exprnode_jrd") - NODE(nod_class_stmtnode_jrd, class_stmtnode_jrd, "class_stmtnode_jrd") - NODE(nod_class_recsrcnode_jrd, class_recsrcnode_jrd, "class_recsrcnode_jrd") - NODE(nod_stmt_expr, stmt_expr, "stmt_expr") - NODE(nod_derived_expr, derived_expr, "derived_expr") - NODE(nod_continue_loop, continue_loop, "") +NODE(nod_class_exprnode_jrd, class_exprnode_jrd, "class_exprnode_jrd") +NODE(nod_class_stmtnode_jrd, class_stmtnode_jrd, "class_stmtnode_jrd") +NODE(nod_class_recsrcnode_jrd, class_recsrcnode_jrd, "class_recsrcnode_jrd") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2010-09-23 09:53:56
|
Revision: 51589 http://firebird.svn.sourceforge.net/firebird/?rev=51589&view=rev Author: robocop Date: 2010-09-23 09:53:50 +0000 (Thu, 23 Sep 2010) Log Message: ----------- Misc. Modified Paths: -------------- firebird/trunk/src/jrd/RecordSourceNodes.h firebird/trunk/src/jrd/evl.cpp firebird/trunk/src/jrd/exe.cpp firebird/trunk/src/jrd/opt.cpp Modified: firebird/trunk/src/jrd/RecordSourceNodes.h =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.h 2010-09-23 09:48:42 UTC (rev 51588) +++ firebird/trunk/src/jrd/RecordSourceNodes.h 2010-09-23 09:53:50 UTC (rev 51589) @@ -45,7 +45,7 @@ class SortNode : public Firebird::PermanentStorage { public: - SortNode(MemoryPool& pool) + explicit SortNode(MemoryPool& pool) : PermanentStorage(pool), unique(false), expressions(pool), @@ -69,7 +69,7 @@ class MapNode : public Firebird::PermanentStorage { public: - MapNode(MemoryPool& pool) + explicit MapNode(MemoryPool& pool) : PermanentStorage(pool), items(pool) { @@ -93,7 +93,7 @@ struct AccessItem { - AccessItem(MemoryPool& pool) + explicit AccessItem(MemoryPool& pool) : relationId(0), indexId(0), indexName(pool) @@ -162,7 +162,7 @@ { } - InversionNode(IndexRetrieval* aRetrieval) + explicit InversionNode(IndexRetrieval* aRetrieval) : type(TYPE_INDEX), impure(0), retrieval(aRetrieval), @@ -224,7 +224,7 @@ stream = value; } - // Identify the streams that make up a RseNode. + // Identify the streams that make up an RseNode. virtual void getStreams(StreamsArray& list) const { list.add(getStream()); Modified: firebird/trunk/src/jrd/evl.cpp =================================================================== --- firebird/trunk/src/jrd/evl.cpp 2010-09-23 09:48:42 UTC (rev 51588) +++ firebird/trunk/src/jrd/evl.cpp 2010-09-23 09:53:50 UTC (rev 51589) @@ -1214,9 +1214,9 @@ continue; } // Note: if the field being SUMed or AVERAGEd is short or long, - // impure will stay long, and the first add will + // impure will stay long, and the first add() will // set the correct scale; if it is approximate numeric, - // the first add will convert impure to double. + // the first add() will convert impure to double. ArithmeticNode::add(desc, impure, node, blr_add); count++; @@ -1244,9 +1244,9 @@ if (request->req_flags & req_null) continue; // Note: if the field being SUMed or AVERAGEd is exact - // numeric, impure will stay int64, and the first add will + // numeric, impure will stay int64, and the first add() will // set the correct scale; if it is approximate numeric, - // the first add will convert impure to double. + // the first add() will convert impure to double. ArithmeticNode::add(desc, impure, node, blr_add); count++; } Modified: firebird/trunk/src/jrd/exe.cpp =================================================================== --- firebird/trunk/src/jrd/exe.cpp 2010-09-23 09:48:42 UTC (rev 51588) +++ firebird/trunk/src/jrd/exe.cpp 2010-09-23 09:53:50 UTC (rev 51589) @@ -3379,7 +3379,7 @@ node->nod_arg[e_sto_relation]->nod_arg[0]); fb_assert(recSource->type == RelationSourceNode::TYPE); - SSHORT stream = recSource->getStream(); + const SSHORT stream = recSource->getStream(); record_param* rpb = &request->req_rpb[stream]; jrd_rel* relation = rpb->rpb_relation; Modified: firebird/trunk/src/jrd/opt.cpp =================================================================== --- firebird/trunk/src/jrd/opt.cpp 2010-09-23 09:48:42 UTC (rev 51588) +++ firebird/trunk/src/jrd/opt.cpp 2010-09-23 09:53:50 UTC (rev 51589) @@ -3711,13 +3711,15 @@ * for the nulls placement flag. * **************************************/ - fb_assert(fromClause->expressions.getCount() <= toClause->expressions.getCount()); - fb_assert(fromClause->expressions.getCount() == fromClause->descending.getCount() && - fromClause->expressions.getCount() == fromClause->nullOrder.getCount()); + const size_t fromCount = fromClause->expressions.getCount(); + + fb_assert(fromCount <= toClause->expressions.getCount()); + fb_assert(fromCount == fromClause->descending.getCount() && + fromCount == fromClause->nullOrder.getCount()); fb_assert(toClause->expressions.getCount() == toClause->descending.getCount() && toClause->expressions.getCount() == toClause->nullOrder.getCount()); - for (size_t i = 0; i < fromClause->expressions.getCount(); ++i) + for (size_t i = 0; i < fromCount; ++i) { toClause->descending[i] = fromClause->descending[i]; toClause->nullOrder[i] = fromClause->nullOrder[i]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ro...@us...> - 2010-09-24 09:23:18
|
Revision: 51597 http://firebird.svn.sourceforge.net/firebird/?rev=51597&view=rev Author: robocop Date: 2010-09-24 09:23:12 +0000 (Fri, 24 Sep 2010) Log Message: ----------- Misc. Modified Paths: -------------- firebird/trunk/src/jrd/Optimizer.cpp firebird/trunk/src/jrd/RecordSourceNodes.cpp firebird/trunk/src/jrd/par.cpp Modified: firebird/trunk/src/jrd/Optimizer.cpp =================================================================== --- firebird/trunk/src/jrd/Optimizer.cpp 2010-09-24 08:33:22 UTC (rev 51596) +++ firebird/trunk/src/jrd/Optimizer.cpp 2010-09-24 09:23:12 UTC (rev 51597) @@ -1116,8 +1116,8 @@ bool usableIndex = true; index_desc::idx_repeat* idx_tail = idx->idx_rpt; NestConst<jrd_nod>* ptr = sortPtr->expressions.begin(); - bool* descending = sortPtr->descending.begin(); - int* nullOrder = sortPtr->nullOrder.begin(); + const bool* descending = sortPtr->descending.begin(); + const int* nullOrder = sortPtr->nullOrder.begin(); for (const NestConst<jrd_nod>* const end = sortPtr->expressions.end(); ptr != end; @@ -2055,7 +2055,7 @@ RseBoolNode* rseNode = boolean->as<RseBoolNode>(); bool forward = true; jrd_nod* value = NULL; - jrd_nod* match; + jrd_nod* match = NULL; if (cmpNode) { Modified: firebird/trunk/src/jrd/RecordSourceNodes.cpp =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-09-24 08:33:22 UTC (rev 51596) +++ firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-09-24 09:23:12 UTC (rev 51597) @@ -258,7 +258,7 @@ stream #2 from view V1 During pass1 of procedure request, the engine tries to expand - all the views into their base tables. It creates a compilier + all the views into their base tables. It creates a compiler scratch block which initially looks like this stream 1 -------- X stream 2 -------- V1 @@ -613,7 +613,7 @@ CompilerScratch::csb_repeat* element = CMP_csb_element(copier.csb, newSource->stream); // SKIDDER: Maybe we need to check if we really found a procedure? element->csb_procedure = MET_lookup_procedure_id(tdbb, newSource->procedure, false, false, 0); - element->csb_view = (jrd_rel*) newSource->view; + element->csb_view = newSource->view; element->csb_view_stream = copier.remap[0]; copier.csb->csb_rpt[newSource->stream].csb_flags |= copier.csb->csb_rpt[stream].csb_flags & csb_no_dbkey; @@ -868,7 +868,7 @@ return rsb; } -// Generate an RecordSource (Record Source Block) for each aggregate operation. +// Generate a RecordSource (Record Source Block) for each aggregate operation. // Generate an AggregateSort (Aggregate SortedStream Block) for each DISTINCT aggregate. RecordSource* AggregateSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt, BoolExprNodeStack* parentStack, UCHAR shellStream) @@ -973,7 +973,7 @@ node->mapStream = stream2; } - SSHORT count = (unsigned int) csb->csb_blr_reader.getByte(); + int count = (unsigned int) csb->csb_blr_reader.getByte(); // Pick up the sub-RseNode's and maps. @@ -1126,7 +1126,7 @@ return rsb; } -// Generate a union complex. +// Generate an union complex. RecordSource* UnionSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt, UCHAR* streams, USHORT nstreams, BoolExprNodeStack* parentStack, UCHAR shellStream) { @@ -1574,7 +1574,7 @@ void RseNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, BoolExprNode** boolean, RecordSourceNodeStack& stack) { - // in the case of a RseNode, it is possible that a new RseNode will be generated, + // in the case of an RseNode, it is possible that a new RseNode will be generated, // so wait to process the source before we push it on the stack (bug 8039) // The addition of the JOIN syntax for specifying inner joins causes an @@ -1707,7 +1707,7 @@ if (opt->rse->rse_jointype != blr_inner) { // Make list of nodes that can be delivered to an outer-stream. - // In fact these are all nodes except when a IS NULL comparision is done. + // In fact these are all nodes except when a IS NULL comparison is done. // Note! Don't forget that this can be burried inside a expression // such as "CASE WHEN (FieldX IS NULL) THEN 0 ELSE 1 END = 0" BoolExprNodeStack::iterator stackItem; @@ -1835,7 +1835,7 @@ CompilerScratch::csb_repeat* tail = &csb->csb_rpt[stream]; // if the plan references a view, find the real base relation - // we are interested in by searching the view map */ + // we are interested in by searching the view map UCHAR* map = NULL; if (tail->csb_map) @@ -2104,7 +2104,7 @@ if (csb->csb_blr_reader.getByte() != blr_map) PAR_syntax_error(csb, "blr_map"); - USHORT count = csb->csb_blr_reader.getWord(); + int count = csb->csb_blr_reader.getWord(); MapNode* node = FB_NEW(csb->csb_pool) MapNode(csb->csb_pool); while (count-- > 0) @@ -2135,7 +2135,7 @@ return (*p > *q) ? 1 : -1; } -// Process a single record source stream from a RseNode. +// Process a single record source stream from an RseNode. // Obviously, if the source is a view, there is more work to do. static void processSource(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, RecordSourceNode* source, BoolExprNode** boolean, RecordSourceNodeStack& stack) @@ -2364,10 +2364,10 @@ // find out how many indices were specified; if // there were none, this is a sequential retrieval - size_t planCount = 0; + //size_t planCount = 0; - if (plan->accessType) - planCount = plan->accessType->items.getCount(); + //if (plan->accessType) + // planCount = plan->accessType->items.getCount(); // go through each of the indices and mark it unusable // for indexed retrieval unless it was specifically mentioned Modified: firebird/trunk/src/jrd/par.cpp =================================================================== --- firebird/trunk/src/jrd/par.cpp 2010-09-24 08:33:22 UTC (rev 51596) +++ firebird/trunk/src/jrd/par.cpp 2010-09-24 09:23:12 UTC (rev 51597) @@ -1727,7 +1727,7 @@ if (node_type == blr_join || node_type == blr_merge) { - USHORT count = (USHORT) csb->csb_blr_reader.getByte(); + int count = (USHORT) csb->csb_blr_reader.getByte(); PlanNode* plan = FB_NEW(csb->csb_pool) PlanNode(csb->csb_pool, PlanNode::TYPE_JOIN); while (count-- > 0) @@ -1834,7 +1834,7 @@ PlanNode::AccessType::TYPE_INDICES); } - USHORT count = (USHORT) csb->csb_blr_reader.getByte(); + int count = (USHORT) csb->csb_blr_reader.getByte(); // pick up the index names and look up the appropriate ids @@ -2135,7 +2135,7 @@ { SET_TDBB(tdbb); - UCHAR blrOp = csb->csb_blr_reader.getByte(); + const UCHAR blrOp = csb->csb_blr_reader.getByte(); if (blrOp != expectedBlr) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <di...@us...> - 2010-10-08 09:40:21
|
Revision: 51643 http://firebird.svn.sourceforge.net/firebird/?rev=51643&view=rev Author: dimitr Date: 2010-10-08 09:40:14 +0000 (Fri, 08 Oct 2010) Log Message: ----------- Fixed problems with recursive PSQL functions. Minor refactoring. Modified Paths: -------------- firebird/trunk/src/jrd/Function.epp firebird/trunk/src/jrd/Function.h firebird/trunk/src/jrd/Routine.h Modified: firebird/trunk/src/jrd/Function.epp =================================================================== --- firebird/trunk/src/jrd/Function.epp 2010-10-08 09:39:34 UTC (rev 51642) +++ firebird/trunk/src/jrd/Function.epp 2010-10-08 09:40:14 UTC (rev 51643) @@ -261,7 +261,6 @@ memset(temp, 0, sizeof(temp)); ULONG length = 0; - function->setUndefined(false); function->fun_inputs = 0; function->fun_defaults = 0; @@ -364,23 +363,20 @@ function->fun_exception_message.printf(EXCEPTION_MESSAGE, function->getName().toString().c_str(), X.RDB$ENTRYPOINT, X.RDB$MODULE_NAME); - if (!X.RDB$LEGACY_FLAG.NULL) - { - function->fun_legacy = (X.RDB$LEGACY_FLAG != 0); - } - if (!X.RDB$INVARIANT_FLAG.NULL) { function->fun_invariant = (X.RDB$INVARIANT_FLAG != 0); } - if (!X.RDB$ENGINE_NAME.NULL) - { - fb_assert(!function->fun_legacy); + function->setUndefined(false); + function->setImplemented(true); - function->fun_entrypoint = NULL; - function->setStatement(NULL); + function->fun_entrypoint = NULL; + function->fun_external = NULL; + function->setStatement(NULL); + if (!X.RDB$ENGINE_NAME.NULL) + { HalfStaticArray<UCHAR, 512> body; if (!X.RDB$FUNCTION_SOURCE.NULL) @@ -395,17 +391,17 @@ body.getBuffer(1)[0] = 0; } - function->fun_external = dbb->dbb_extManager.makeFunction( - tdbb, function, X.RDB$ENGINE_NAME, + function->fun_external = + dbb->dbb_extManager.makeFunction(tdbb, function, X.RDB$ENGINE_NAME, (X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin()); + + if (!function->fun_external) + { + function->setImplemented(false); + } } else if (!X.RDB$FUNCTION_BLR.NULL) { - fb_assert(!function->fun_legacy); - - function->fun_external = NULL; - function->fun_entrypoint = NULL; - MemoryPool* const csb_pool = dbb->createPool(); Jrd::ContextPoolHolder context(tdbb, csb_pool); @@ -436,32 +432,28 @@ function->makeFormat(); } - else + else if (!X.RDB$MODULE_NAME.NULL && !X.RDB$ENTRYPOINT.NULL) { - function->fun_external = NULL; - function->setStatement(NULL); + function->fun_entrypoint = + Module::lookup(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT, dbb->dbb_modules); - if (!X.RDB$MODULE_NAME.NULL && !X.RDB$ENTRYPOINT.NULL) + // Could not find a function with given MODULE, ENTRYPOINT. + // Try the list of internally implemented functions. + if (!function->fun_entrypoint) { - fb_assert(function->fun_legacy); - function->fun_entrypoint = - Module::lookup(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT, dbb->dbb_modules); - - // Could not find a function with given MODULE, ENTRYPOINT. - // Try the list of internally implemented functions. - if (!function->fun_entrypoint) - { - function->fun_entrypoint = - BUILTIN_entrypoint(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT); - } + BUILTIN_entrypoint(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT); } - else + + if (!function->fun_entrypoint) { - function->fun_entrypoint = NULL; - function->setUndefined(true); + function->setImplemented(false); } } + else + { + function->setUndefined(true); + } if (X.RDB$VALID_BLR.NULL || X.RDB$VALID_BLR == FALSE) { @@ -704,9 +696,8 @@ { fun_external->execute(tdbb, args, value); } - else + else if (getStatement()) { - fb_assert(getStatement()); fb_assert(!fun_return_arg); fb_assert(args->nod_count == fun_inputs); @@ -805,6 +796,10 @@ MOV_move(tdbb, &arg_desc, &value->vlu_desc); } } + else + { + fb_assert(false); + } return (request->req_flags & req_null) ? NULL : &value->vlu_desc; } Modified: firebird/trunk/src/jrd/Function.h =================================================================== --- firebird/trunk/src/jrd/Function.h 2010-10-08 09:39:34 UTC (rev 51642) +++ firebird/trunk/src/jrd/Function.h 2010-10-08 09:40:14 UTC (rev 51643) @@ -76,7 +76,6 @@ fun_existence_lock(NULL), fun_alter_count(0), fun_exception_message(p), - fun_legacy(true), fun_invariant(false), fun_external(NULL) { @@ -117,7 +116,6 @@ Firebird::string fun_exception_message; // message containing the exception error message - bool fun_legacy; bool fun_invariant; const ExtEngineManager::Function* fun_external; }; Modified: firebird/trunk/src/jrd/Routine.h =================================================================== --- firebird/trunk/src/jrd/Routine.h 2010-10-08 09:39:34 UTC (rev 51642) +++ firebird/trunk/src/jrd/Routine.h 2010-10-08 09:40:14 UTC (rev 51643) @@ -38,7 +38,8 @@ name(p), securityName(p), statement(NULL), - undefined(false) + undefined(false), + implemented(true) { } @@ -63,6 +64,9 @@ bool isUndefined() const { return undefined; } void setUndefined(bool value) { undefined = value; } + bool isImplemented() const { return implemented; } + void setImplemented(bool value) { implemented = value; } + public: virtual int getObjectType() const = 0; virtual SLONG getSclType() const = 0; @@ -73,6 +77,7 @@ Firebird::MetaName securityName; // security class name JrdStatement* statement; // compiled routine statement bool undefined; // Is the packaged routine missing the body/entrypoint? + bool implemented; // routine has its implementation available }; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <hv...@us...> - 2010-10-08 11:58:04
|
Revision: 51644 http://firebird.svn.sourceforge.net/firebird/?rev=51644&view=rev Author: hvlad Date: 2010-10-08 11:57:57 +0000 (Fri, 08 Oct 2010) Log Message: ----------- Fixed bug CORE-3170 : Engine could enter infinite loop if EVENT's are posted but no subscribers exists Modified Paths: -------------- firebird/trunk/src/jrd/dfw.epp firebird/trunk/src/jrd/event.cpp firebird/trunk/src/jrd/event_proto.h firebird/trunk/src/jrd/jrd.cpp Modified: firebird/trunk/src/jrd/dfw.epp =================================================================== --- firebird/trunk/src/jrd/dfw.epp 2010-10-08 09:40:14 UTC (rev 51643) +++ firebird/trunk/src/jrd/dfw.epp 2010-10-08 11:57:57 UTC (rev 51644) @@ -851,7 +851,7 @@ switch (work->dfw_type) { case dfw_post_event: - EventManager::init(dbb); + EventManager::init(transaction->tra_attachment); dbb->dbb_event_mgr->postEvent(lock->lck_length, (const TEXT*) &lock->lck_key, work->dfw_name.length(), work->dfw_name.c_str(), Modified: firebird/trunk/src/jrd/event.cpp =================================================================== --- firebird/trunk/src/jrd/event.cpp 2010-10-08 09:40:14 UTC (rev 51643) +++ firebird/trunk/src/jrd/event.cpp 2010-10-08 11:57:57 UTC (rev 51644) @@ -43,6 +43,7 @@ #include "../jrd/os/isc_i_proto.h" #include "../common/utils_proto.h" #include "../jrd/Database.h" +#include "../jrd/Attachment.h" #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -74,15 +75,16 @@ GlobalPtr<Mutex> EventManager::g_mapMutex; -void EventManager::init(Database* dbb) +void EventManager::init(Attachment* attachment) { - if (!dbb->dbb_event_mgr) + Database* dbb = attachment->att_database; + EventManager* eventMgr = dbb->dbb_event_mgr; + if (!eventMgr) { const Firebird::string id = dbb->getUniqueFileId(); Firebird::MutexLockGuard guard(g_mapMutex); - EventManager* eventMgr = NULL; if (!g_emMap->get(id, eventMgr)) { eventMgr = new EventManager(id, dbb->dbb_config); @@ -92,6 +94,10 @@ dbb->dbb_event_mgr = eventMgr; } + + if (!attachment->att_event_session) { + attachment->att_event_session = eventMgr->create_session(); + } } @@ -193,7 +199,7 @@ } -SLONG EventManager::createSession() +SLONG EventManager::create_session() { /************************************** * Modified: firebird/trunk/src/jrd/event_proto.h =================================================================== --- firebird/trunk/src/jrd/event_proto.h 2010-10-08 09:40:14 UTC (rev 51643) +++ firebird/trunk/src/jrd/event_proto.h 2010-10-08 11:57:57 UTC (rev 51644) @@ -36,7 +36,7 @@ namespace Jrd { -class Database; +class Attachment; class EventManager : public Firebird::RefCounted, public Firebird::GlobalStorage, public SharedMemory<evh> { @@ -48,12 +48,11 @@ const int PID; public: - static void init(Database*); + static void init(Attachment*); EventManager(const Firebird::string& id, Firebird::RefPtr<Config> conf); ~EventManager(); - SLONG createSession(); void deleteSession(SLONG); SLONG queEvents(SLONG, USHORT, const TEXT*, USHORT, const UCHAR*, @@ -69,6 +68,7 @@ void acquire_shmem(); frb* alloc_global(UCHAR type, ULONG length, bool recurse); void create_process(); + SLONG create_session(); void delete_event(evnt*); void delete_process(SLONG); void delete_request(evt_req*); Modified: firebird/trunk/src/jrd/jrd.cpp =================================================================== --- firebird/trunk/src/jrd/jrd.cpp 2010-10-08 09:40:14 UTC (rev 51643) +++ firebird/trunk/src/jrd/jrd.cpp 2010-10-08 11:57:57 UTC (rev 51644) @@ -2933,13 +2933,8 @@ Database* const dbb = tdbb->getDatabase(); Lock* const lock = dbb->dbb_lock; - EventManager::init(dbb); + EventManager::init(attachment); - if (!attachment->att_event_session) - { - attachment->att_event_session = dbb->dbb_event_mgr->createSession(); - } - *id = dbb->dbb_event_mgr->queEvents(attachment->att_event_session, lock->lck_length, (const TEXT*) &lock->lck_key, length, items, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ale...@us...> - 2010-10-12 11:37:00
|
Revision: 51659 http://firebird.svn.sourceforge.net/firebird/?rev=51659&view=rev Author: alexpeshkoff Date: 2010-10-12 11:36:51 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Restored a lot of changes, rolled back by me unintentionally Modified Paths: -------------- firebird/trunk/src/jrd/Attachment.h firebird/trunk/src/jrd/Collation.cpp firebird/trunk/src/jrd/Collation.h firebird/trunk/src/jrd/DatabaseSnapshot.cpp firebird/trunk/src/jrd/ExtEngineManager.cpp firebird/trunk/src/jrd/ExtEngineManager.h firebird/trunk/src/jrd/Function.epp firebird/trunk/src/jrd/Function.h firebird/trunk/src/jrd/JrdStatement.cpp firebird/trunk/src/jrd/JrdStatement.h firebird/trunk/src/jrd/Optimizer.cpp firebird/trunk/src/jrd/Optimizer.h firebird/trunk/src/jrd/Relation.h firebird/trunk/src/jrd/Routine.h firebird/trunk/src/jrd/SimilarToMatcher.h firebird/trunk/src/jrd/SysFunction.cpp firebird/trunk/src/jrd/ValuesImpl.cpp firebird/trunk/src/jrd/ValuesImpl.h firebird/trunk/src/jrd/blb.cpp firebird/trunk/src/jrd/blob_filter.cpp firebird/trunk/src/jrd/build_no.h firebird/trunk/src/jrd/cch.cpp firebird/trunk/src/jrd/cmp.cpp firebird/trunk/src/jrd/cmp_proto.h firebird/trunk/src/jrd/dfw.epp firebird/trunk/src/jrd/dyn.epp firebird/trunk/src/jrd/event.cpp firebird/trunk/src/jrd/event_proto.h firebird/trunk/src/jrd/evl.cpp firebird/trunk/src/jrd/evl_proto.h firebird/trunk/src/jrd/exe.cpp firebird/trunk/src/jrd/exe.h firebird/trunk/src/jrd/execute_statement.cpp firebird/trunk/src/jrd/ext.cpp firebird/trunk/src/jrd/extds/ExtDS.cpp firebird/trunk/src/jrd/extds/InternalDS.cpp firebird/trunk/src/jrd/fun.epp firebird/trunk/src/jrd/intl_classes.h firebird/trunk/src/jrd/jrd.cpp firebird/trunk/src/jrd/jrd.h firebird/trunk/src/jrd/lls.h firebird/trunk/src/jrd/met.epp firebird/trunk/src/jrd/met_proto.h firebird/trunk/src/jrd/nbak.cpp firebird/trunk/src/jrd/nod.h firebird/trunk/src/jrd/opt.cpp firebird/trunk/src/jrd/opt_proto.h firebird/trunk/src/jrd/par.cpp firebird/trunk/src/jrd/par_proto.h firebird/trunk/src/jrd/pcmet.epp firebird/trunk/src/jrd/recsrc/AggregatedStream.cpp firebird/trunk/src/jrd/recsrc/BitmapTableScan.cpp firebird/trunk/src/jrd/recsrc/FilteredStream.cpp firebird/trunk/src/jrd/recsrc/HashJoin.cpp firebird/trunk/src/jrd/recsrc/IndexTableScan.cpp firebird/trunk/src/jrd/recsrc/MergeJoin.cpp firebird/trunk/src/jrd/recsrc/NestedLoopJoin.cpp firebird/trunk/src/jrd/recsrc/ProcedureScan.cpp firebird/trunk/src/jrd/recsrc/RecordSource.cpp firebird/trunk/src/jrd/recsrc/RecordSource.h firebird/trunk/src/jrd/recsrc/RecursiveStream.cpp firebird/trunk/src/jrd/recsrc/Union.cpp firebird/trunk/src/jrd/recsrc/VirtualTableScan.cpp firebird/trunk/src/jrd/recsrc/WindowedStream.cpp firebird/trunk/src/jrd/rse.h firebird/trunk/src/jrd/scl.epp firebird/trunk/src/jrd/svc.cpp firebird/trunk/src/jrd/trace/TraceObjects.cpp firebird/trunk/src/jrd/trig.h firebird/trunk/src/jrd/vio.cpp Modified: firebird/trunk/src/jrd/Attachment.h =================================================================== --- firebird/trunk/src/jrd/Attachment.h 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/Attachment.h 2010-10-12 11:36:51 UTC (rev 51659) @@ -70,7 +70,6 @@ class IndexLock; class ArrayField; struct sort_context; - class RecordSelExpr; class vcl; class TextType; class Parameter; Modified: firebird/trunk/src/jrd/Collation.cpp =================================================================== --- firebird/trunk/src/jrd/Collation.cpp 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/Collation.cpp 2010-10-12 11:36:51 UTC (rev 51659) @@ -725,6 +725,7 @@ typename pContainsMatcher, typename pLikeMatcher, typename pSimilarToMatcher, + typename pSubstringSimilarMatcher, typename pMatchesMatcher, typename pSleuthMatcher > @@ -780,18 +781,23 @@ } virtual bool similarTo(MemoryPool& pool, const UCHAR* s, SLONG sl, - const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escapeLen, bool forSubstring) + const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escapeLen) { - return pSimilarToMatcher::evaluate(pool, this, s, sl, p, pl, escape, - escapeLen, forSubstring); + return pSimilarToMatcher::evaluate(pool, this, s, sl, p, pl, escape, escapeLen); } - virtual BaseSimilarToMatcher* createSimilarToMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl, - const UCHAR* escape, SLONG escapeLen, bool forSubstring) + virtual PatternMatcher* createSimilarToMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl, + const UCHAR* escape, SLONG escapeLen) { - return pSimilarToMatcher::create(pool, this, p, pl, escape, escapeLen, forSubstring); + return pSimilarToMatcher::create(pool, this, p, pl, escape, escapeLen); } + virtual BaseSubstringSimilarMatcher* createSubstringSimilarMatcher(MemoryPool& pool, + const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escapeLen) + { + return pSubstringSimilarMatcher::create(pool, this, p, pl, escape, escapeLen); + } + virtual bool contains(MemoryPool& pool, const UCHAR* s, SLONG sl, const UCHAR* p, SLONG pl) { return pContainsMatcher::evaluate(pool, this, s, sl, p, pl); @@ -817,6 +823,7 @@ ContainsMatcherUCharDirect, LikeMatcher<T>, SimilarToMatcher<T>, + SubstringSimilarMatcher<T>, MatchesMatcher<T>, SleuthMatcher<T> > DirectImpl; @@ -826,6 +833,7 @@ ContainsMatcher<T>, LikeMatcher<T>, SimilarToMatcher<T>, + SubstringSimilarMatcher<T>, MatchesMatcher<T>, SleuthMatcher<T> > NonDirectImpl; Modified: firebird/trunk/src/jrd/Collation.h =================================================================== --- firebird/trunk/src/jrd/Collation.h 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/Collation.h 2010-10-12 11:36:51 UTC (rev 51659) @@ -66,10 +66,13 @@ const UCHAR* escape, SLONG escapeLen) = 0; virtual bool similarTo(MemoryPool& pool, const UCHAR* s, SLONG sl, const UCHAR* p, SLONG pl, - const UCHAR* escape, SLONG escapeLen, bool forSubstring) = 0; - virtual BaseSimilarToMatcher* createSimilarToMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl, - const UCHAR* escape, SLONG escapeLen, bool forSubstring) = 0; + const UCHAR* escape, SLONG escapeLen) = 0; + virtual PatternMatcher* createSimilarToMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl, + const UCHAR* escape, SLONG escapeLen) = 0; + virtual BaseSubstringSimilarMatcher* createSubstringSimilarMatcher(MemoryPool& pool, + const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escapeLen) = 0; + virtual bool contains(MemoryPool& pool, const UCHAR* s, SLONG sl, const UCHAR* p, SLONG pl) = 0; virtual PatternMatcher* createContainsMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl) = 0; Modified: firebird/trunk/src/jrd/DatabaseSnapshot.cpp =================================================================== --- firebird/trunk/src/jrd/DatabaseSnapshot.cpp 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/DatabaseSnapshot.cpp 2010-10-12 11:36:51 UTC (rev 51659) @@ -918,7 +918,7 @@ } -bool DatabaseSnapshot::putAttachment(thread_db* tdbb, const Jrd::Attachment* attachment, +bool DatabaseSnapshot::putAttachment(thread_db* /*tdbb*/, const Jrd::Attachment* attachment, Writer& writer, int stat_id) { fb_assert(attachment); Modified: firebird/trunk/src/jrd/ExtEngineManager.cpp =================================================================== --- firebird/trunk/src/jrd/ExtEngineManager.cpp 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/ExtEngineManager.cpp 2010-10-12 11:36:51 UTC (rev 51659) @@ -388,7 +388,7 @@ } -void ExtEngineManager::Function::execute(thread_db* tdbb, const jrd_nod* args, impure_value* impure) +void ExtEngineManager::Function::execute(thread_db* tdbb, const jrd_nod* args, impure_value* impure) const { EngineAttachmentInfo* attInfo = extManager->getEngineAttachment(tdbb, engine); ContextManager<ExternalFunction> ctxManager(tdbb, attInfo, function, @@ -564,7 +564,7 @@ void ExtEngineManager::Trigger::execute(thread_db* tdbb, ExternalTrigger::Action action, - record_param* oldRpb, record_param* newRpb) + record_param* oldRpb, record_param* newRpb) const { EngineAttachmentInfo* attInfo = extManager->getEngineAttachment(tdbb, engine); ContextManager<ExternalTrigger> ctxManager(tdbb, attInfo, trigger, @@ -612,9 +612,9 @@ } -int ExtEngineManager::Trigger::setValues(thread_db* tdbb, MemoryPool& pool, +int ExtEngineManager::Trigger::setValues(thread_db* /*tdbb*/, MemoryPool& pool, AutoPtr<ValuesImpl>& values, Array<dsc*>& descs, - record_param* rpb) + record_param* rpb) const { if (!rpb || !rpb->rpb_record) return 0; Modified: firebird/trunk/src/jrd/ExtEngineManager.h =================================================================== --- firebird/trunk/src/jrd/ExtEngineManager.h 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/ExtEngineManager.h 2010-10-12 11:36:51 UTC (rev 51659) @@ -130,7 +130,7 @@ const Jrd::Function* aUdf); ~Function(); - void execute(thread_db* tdbb, const jrd_nod* args, impure_value* impure); + void execute(thread_db* tdbb, const jrd_nod* args, impure_value* impure) const; private: ExtEngineManager* extManager; @@ -191,12 +191,12 @@ ~Trigger(); void execute(thread_db* tdbb, Firebird::ExternalTrigger::Action action, - record_param* oldRpb, record_param* newRpb); + record_param* oldRpb, record_param* newRpb) const; private: int setValues(thread_db* tdbb, Firebird::MemoryPool& pool, Firebird::AutoPtr<ValuesImpl>& values, Firebird::Array<dsc*>& descs, - record_param* rpb); + record_param* rpb) const; ExtEngineManager* extManager; Firebird::ExternalEngine* engine; Modified: firebird/trunk/src/jrd/Function.epp =================================================================== --- firebird/trunk/src/jrd/Function.epp 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/Function.epp 2010-10-12 11:36:51 UTC (rev 51659) @@ -228,7 +228,7 @@ AutoCacheRequest request_fun(tdbb, irq_l_functions, IRQ_REQUESTS); - fun_repeat temp[MAX_UDF_ARGUMENTS + 1]; + Argument temp[MAX_UDF_ARGUMENTS + 1]; FOR(REQUEST_HANDLE request_fun) X IN RDB$FUNCTIONS @@ -261,7 +261,6 @@ memset(temp, 0, sizeof(temp)); ULONG length = 0; - function->setUndefined(false); function->fun_inputs = 0; function->fun_defaults = 0; @@ -276,7 +275,7 @@ if (Y.RDB$ARGUMENT_POSITION != X.RDB$RETURN_ARGUMENT) function->fun_inputs++; - fun_repeat* const tail = temp + Y.RDB$ARGUMENT_POSITION; + Argument* const tail = temp + Y.RDB$ARGUMENT_POSITION; tail->fun_mechanism = (FUN_T) Y.RDB$MECHANISM; Parameter* const parameter = FB_NEW(*dbb->dbb_permanent) Parameter(*dbb->dbb_permanent); @@ -334,7 +333,7 @@ try { parameter->prm_default_value = - MET_parse_blob(tdbb, NULL, &default_value, NULL, NULL, false); + MET_parse_blob(tdbb, NULL, &default_value, NULL, NULL, false, false); } catch (const Exception&) { @@ -356,7 +355,7 @@ function->fun_return_arg = X.RDB$RETURN_ARGUMENT; function->fun_temp_length = length; function->fun_args.resize(count + 1); - memcpy(function->fun_args.begin(), temp, function->fun_args.getCount() * sizeof(fun_repeat)); + memcpy(function->fun_args.begin(), temp, function->fun_args.getCount() * sizeof(Argument)); // Prepare the exception message to be used in case this function ever // causes an exception. This is done at this time to save us from preparing @@ -364,23 +363,20 @@ function->fun_exception_message.printf(EXCEPTION_MESSAGE, function->getName().toString().c_str(), X.RDB$ENTRYPOINT, X.RDB$MODULE_NAME); - if (!X.RDB$LEGACY_FLAG.NULL) - { - function->fun_legacy = (X.RDB$LEGACY_FLAG != 0); - } - if (!X.RDB$INVARIANT_FLAG.NULL) { function->fun_invariant = (X.RDB$INVARIANT_FLAG != 0); } - if (!X.RDB$ENGINE_NAME.NULL) - { - fb_assert(!function->fun_legacy); + function->setUndefined(false); + function->setImplemented(true); - function->fun_entrypoint = NULL; - function->setStatement(NULL); + function->fun_entrypoint = NULL; + function->fun_external = NULL; + function->setStatement(NULL); + if (!X.RDB$ENGINE_NAME.NULL) + { HalfStaticArray<UCHAR, 512> body; if (!X.RDB$FUNCTION_SOURCE.NULL) @@ -395,17 +391,17 @@ body.getBuffer(1)[0] = 0; } - function->fun_external = dbb->dbb_extManager.makeFunction( - tdbb, function, X.RDB$ENGINE_NAME, + function->fun_external = + dbb->dbb_extManager.makeFunction(tdbb, function, X.RDB$ENGINE_NAME, (X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin()); + + if (!function->fun_external) + { + function->setImplemented(false); + } } else if (!X.RDB$FUNCTION_BLR.NULL) { - fb_assert(!function->fun_legacy); - - function->fun_external = NULL; - function->fun_entrypoint = NULL; - MemoryPool* const csb_pool = dbb->createPool(); Jrd::ContextPoolHolder context(tdbb, csb_pool); @@ -436,32 +432,28 @@ function->makeFormat(); } - else + else if (!X.RDB$MODULE_NAME.NULL && !X.RDB$ENTRYPOINT.NULL) { - function->fun_external = NULL; - function->setStatement(NULL); + function->fun_entrypoint = + Module::lookup(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT, dbb->dbb_modules); - if (!X.RDB$MODULE_NAME.NULL && !X.RDB$ENTRYPOINT.NULL) + // Could not find a function with given MODULE, ENTRYPOINT. + // Try the list of internally implemented functions. + if (!function->fun_entrypoint) { - fb_assert(function->fun_legacy); - function->fun_entrypoint = - Module::lookup(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT, dbb->dbb_modules); - - // Could not find a function with given MODULE, ENTRYPOINT. - // Try the list of internally implemented functions. - if (!function->fun_entrypoint) - { - function->fun_entrypoint = - BUILTIN_entrypoint(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT); - } + BUILTIN_entrypoint(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT); } - else + + if (!function->fun_entrypoint) { - function->fun_entrypoint = NULL; - function->setUndefined(true); + function->setImplemented(false); } } + else + { + function->setUndefined(true); + } if (X.RDB$VALID_BLR.NULL || X.RDB$VALID_BLR == FALSE) { @@ -561,7 +553,7 @@ } } -ULONG Function::allocateImpure(CompilerScratch* csb) +ULONG Function::allocateImpure(CompilerScratch* csb) const { const ULONG impure = CMP_impure(csb, sizeof(impure_value)); @@ -594,7 +586,7 @@ statement = NULL; } - MET_parse_blob(tdbb, NULL, blob_id, &csb, &statement, false); + MET_parse_blob(tdbb, NULL, blob_id, &csb, &statement, false, false); statement->function = this; setStatement(statement); } @@ -668,7 +660,7 @@ jrd_req* const request = tdbb->getRequest(); - const fun_repeat* const return_ptr = &fun_args[fun_return_arg]; + const Argument* const return_ptr = &fun_args[fun_return_arg]; value->vlu_desc = return_ptr->fun_parameter->prm_desc; // If the return data type is any of the string types, @@ -704,9 +696,8 @@ { fun_external->execute(tdbb, args, value); } - else + else if (getStatement()) { - fb_assert(getStatement()); fb_assert(!fun_return_arg); fb_assert(args->nod_count == fun_inputs); @@ -805,6 +796,10 @@ MOV_move(tdbb, &arg_desc, &value->vlu_desc); } } + else + { + fb_assert(false); + } return (request->req_flags & req_null) ? NULL : &value->vlu_desc; } Modified: firebird/trunk/src/jrd/Function.h =================================================================== --- firebird/trunk/src/jrd/Function.h 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/Function.h 2010-10-12 11:36:51 UTC (rev 51659) @@ -23,22 +23,23 @@ #include "../jrd/Routine.h" #include "../common/classes/array.h" #include "../common/dsc.h" +#include "../common/classes/NestConst.h" #include "../jrd/val.h" namespace Jrd { - struct fun_repeat - { - Parameter* fun_parameter; // parameter info - FUN_T fun_mechanism; // passing mechanism - }; - class Function : public Routine { static const USHORT MAX_ALTER_COUNT = 64; // Number of times an in-cache function can be altered static const char* const EXCEPTION_MESSAGE; public: + struct Argument + { + NestConst<Parameter> fun_parameter; // parameter info + FUN_T fun_mechanism; // passing mechanism + }; + static Function* lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags); static Function* lookup(thread_db* tdbb, const Firebird::QualifiedName& name, bool noscan); @@ -55,7 +56,7 @@ dsc* execute(thread_db* tdbb, const jrd_nod* args, impure_value* value) const; void releaseLocks(thread_db* tdbb); void remove(thread_db* tdbb); - ULONG allocateImpure(CompilerScratch* csb); + ULONG allocateImpure(CompilerScratch* csb) const; void parseBlr(thread_db* tdbb, bid* blob_id, CompilerScratch* csb); jrd_nod* parseArgs(thread_db* tdbb, CompilerScratch* csb); @@ -75,7 +76,6 @@ fun_existence_lock(NULL), fun_alter_count(0), fun_exception_message(p), - fun_legacy(true), fun_invariant(false), fun_external(NULL) { @@ -107,7 +107,7 @@ Format fun_in_msg_format; Format fun_out_msg_format; - Firebird::Array<fun_repeat> fun_args; + Firebird::Array<Argument> fun_args; USHORT fun_flags; // flags USHORT fun_use_count; // requests compiled with function @@ -116,9 +116,8 @@ Firebird::string fun_exception_message; // message containing the exception error message - bool fun_legacy; bool fun_invariant; - ExtEngineManager::Function* fun_external; + const ExtEngineManager::Function* fun_external; }; const USHORT FUN_scanned = 1; // Field expressions scanned Modified: firebird/trunk/src/jrd/JrdStatement.cpp =================================================================== --- firebird/trunk/src/jrd/JrdStatement.cpp 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/JrdStatement.cpp 2010-10-12 11:36:51 UTC (rev 51659) @@ -138,8 +138,7 @@ // make a vector of all invariant-type nodes, so that we will // be able to easily reinitialize them when we restart the request - for (Array<jrd_nod*>::iterator i = csb->csb_invariants.begin(); i != csb->csb_invariants.end(); ++i) - invariants.add(*i); + invariants.join(csb->csb_invariants); rpbsSetup.grow(csb->csb_n_stream); Modified: firebird/trunk/src/jrd/JrdStatement.h =================================================================== --- firebird/trunk/src/jrd/JrdStatement.h 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/JrdStatement.h 2010-10-12 11:36:51 UTC (rev 51659) @@ -77,7 +77,7 @@ const jrd_nod* topNode; // top of execution tree Firebird::Array<const RecordSource*> fors; // record sources Firebird::Array<const jrd_nod*> execStmts; // exec_into nodes - Firebird::Array<const jrd_nod*> invariants; // invariant nodes + Firebird::Array<ULONG*> invariants; // pointer to nodes invariant offsets Firebird::RefStrPtr sqlText; // SQL text (encoded in the metadata charset) Firebird::Array<UCHAR> blr; // BLR for non-SQL query MapFieldInfo mapFieldInfo; // Map field name to field info Modified: firebird/trunk/src/jrd/Optimizer.cpp =================================================================== --- firebird/trunk/src/jrd/Optimizer.cpp 2010-10-12 11:34:14 UTC (rev 51658) +++ firebird/trunk/src/jrd/Optimizer.cpp 2010-10-12 11:36:51 UTC (rev 51659) @@ -36,7 +36,9 @@ #include "../jrd/rse.h" #include "../jrd/ods.h" #include "../jrd/Optimizer.h" +#include "../jrd/RecordSourceNodes.h" #include "../jrd/recsrc/RecordSource.h" +#include "../dsql/BoolNodes.h" #include "../dsql/ExprNodes.h" #include "../dsql/StmtNodes.h" @@ -89,56 +91,18 @@ DEV_BLKCHK(csb, type_csb); DEV_BLKCHK(node, type_nod); - if (node->nod_flags & nod_deoptimize) { - return false; - } - // Recurse thru interesting sub-nodes switch (node->nod_type) { - case nod_procedure: - { - jrd_nod* inputs = node->nod_arg[e_prc_inputs]; - if (inputs) - { - fb_assert(inputs->nod_type == nod_asn_list); - jrd_nod* const* ptr = inputs->nod_arg; - for (const jrd_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++) - { - if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) { - return false; - } - } - } - break; - } + case nod_class_recsrcnode_jrd: + return reinterpret_cast<RecordSourceNode*>(node->nod_arg[0])->computable( + csb, stream, idx_use, allowOnlyCurrentStream, NULL); - case nod_union: - { - jrd_nod* clauses = node->nod_arg[e_uni_clauses]; - jrd_nod* const* ptr = clauses->nod_arg; - for (const jrd_nod* const* const end = ptr + clauses->nod_count; ptr < end; ptr += 2) - { - if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) { - return false; - } - } - break; - } - case nod_class_exprnode_jrd: { ExprNode* exprNode = reinterpret_cast<ExprNode*>(node->nod_arg[0]); - - for (NestConst<NestConst<jrd_nod> >* i = exprNode->jrdChildNodes.begin(); - i != exprNode->jrdChildNodes.end(); ++i) - { - if (!OPT_computable(csb, **i, stream, idx_use, allowOnlyCurrentStream)) - return false; - } - - break; + return exprNode->computable(csb, stream, idx_use, allowOnlyCurrentStream); } default: @@ -146,17 +110,13 @@ jrd_nod* const* ptr = node->nod_arg; for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++) { - if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) { + if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) return false; - } } break; } } - RecordSelExpr* rse; - jrd_nod* sub; - jrd_nod* value; USHORT n; switch (node->nod_type) @@ -166,15 +126,12 @@ if (allowOnlyCurrentStream) { if (n != stream && !(csb->csb_rpt[n].csb_flags & csb_sub_stream)) - { return false; - } } else { - if (n == stream) { + if (n == stream) return false; - } } return csb->csb_rpt[n].csb_flags & csb_active; @@ -225,115 +182,24 @@ case nod_total: case nod_count: case nod_from: - if ((sub = node->nod_arg[e_stat_default]) && - !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) { - return false; - } - rse = (RecordSelExpr*) node->nod_arg[e_stat_rse]; - value = node->nod_arg[e_stat_value]; - break; + jrd_nod* sub; - case nod_rse: - rse = (RecordSelExpr*) node; - value = NULL; - break; - - case nod_aggregate: - rse = (RecordSelExpr*) node->nod_arg[e_agg_rse]; - rse->rse_sorted = node->nod_arg[e_agg_group]; - value = NULL; - break; - - case nod_window: - rse = (RecordSelExpr*) node->nod_arg[e_win_rse]; - value = NULL; - break; - - default: - return true; - } - - // Node is a record selection expression. - bool result = true; - - if ((sub = rse->rse_first) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) { - return false; - } - - if ((sub = rse->rse_skip) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) { - return false; - } - - // Set sub-streams of rse active - jrd_nod* const* ptr; - const jrd_nod* const* end; - - for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end; ptr++) - { - const jrd_nod* const node = *ptr; - - if (node->nod_type == nod_window) - { - const jrd_nod* windows = node->nod_arg[e_win_windows]; - - for (unsigned i = 0; i < windows->nod_count; ++i) + if ((sub = node->nod_arg[e_stat_default]) && + !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) { - n = (USHORT)(IPTR) windows->nod_arg[i]->nod_arg[e_part_stream]; - csb->csb_rpt[n].csb_flags |= (csb_active | csb_sub_stream); + return false; } - } - else if (node->nod_type != nod_rse) - { - n = (USHORT)(IPTR) node->nod_arg[STREAM_INDEX(node)]; - csb->csb_rpt[n].csb_flags |= (csb_active | csb_sub_stream); - } - } - // Check sub-stream - if (((sub = rse->rse_boolean) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) || - ((sub = rse->rse_sorted) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream)) || - ((sub = rse->rse_projection) && !OPT_computable(csb, sub, stream, idx_use, allowOnlyCurrentStream))) - { - result = false; - } + fb_assert(node->nod_arg[e_stat_rse]->nod_type == nod_class_recsrcnode_jrd); + RseNode* rse = reinterpret_cast<RseNode*>(node->nod_arg[e_stat_rse]->nod_arg[0]); - for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end && result; ptr++) - { - if (!OPT_computable(csb, (*ptr), stream, idx_use, allowOnlyCurrentStream)) - { - result = false; + return rse->computable(csb, stream, idx_use, allowOnlyCurrentStream, + node->nod_arg[e_stat_value]); } } - // Check value expression, if any - if (result && value && !OPT_computable(csb, value, stream, idx_use, allowOnlyCurrentStream)) { - result = false; - } - - // Reset streams inactive - for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end; ptr++) - { - const jrd_nod* const node = *ptr; - - if (node->nod_type == nod_window) - { - const jrd_nod* windows = node->nod_arg[e_win_windows]; - - for (unsigned i = 0; i < windows->nod_count; ++i) - { - n = (USHORT)(IPTR) windows->nod_arg[i]->nod_arg[e_part_stream]; - csb->csb_rpt[n].csb_flags &= ~(csb_active | csb_sub_stream); - } - } - else if (node->nod_type != nod_rse) - { - n = (USHORT)(IPTR) (*ptr)->nod_arg[STREAM_INDEX((*ptr))]; - csb->csb_rpt[n].csb_flags &= ~(csb_active | csb_sub_stream); - } - } - - return result; + return true; } @@ -389,9 +255,7 @@ SET_TDBB(tdbb); if (!node1 || !node2) - { BUGCHECK(303); // msg 303 Invalid expression for evaluation. - } if (node1->nod_type != node2->nod_type) { @@ -430,86 +294,10 @@ { ExprNode* exprNode1 = reinterpret_cast<ExprNode*>(node1->nod_arg[0]); ExprNode* exprNode2 = reinterpret_cast<ExprNode*>(node2->nod_arg[0]); - Array<NestConst<NestConst<jrd_nod> > >& children1 = exprNode1->jrdChildNodes; - Array<NestConst<NestConst<jrd_nod> > >& children2 = exprNode2->jrdChildNodes; - if (exprNode1->type != exprNode2->type || children1.getCount() != children2.getCount()) - return false; - - switch (exprNode1->type) - { - case ExprNode::TYPE_SYSFUNC_CALL: - case ExprNode::TYPE_UDF_CALL: - switch (exprNode1->type) - { - case ExprNode::TYPE_SYSFUNC_CALL: - if (!exprNode1->as<SysFuncCallNode>()->function || - exprNode1->as<SysFuncCallNode>()->function != exprNode2->as<SysFuncCallNode>()->function) - { - return false; - } - break; - - case ExprNode::TYPE_UDF_CALL: - if (!exprNode1->as<UdfCallNode>()->function || - exprNode1->as<UdfCallNode>()->function != exprNode2->as<UdfCallNode>()->function) - { - return false; - } - break; - } - // fall into - - case ExprNode::TYPE_CONCATENATE: - case ExprNode::TYPE_SUBSTRING_SIMILAR: - for (NestConst<NestConst<jrd_nod> >* i = children1.begin(), *j = children2.begin(); - i != children1.end(); ++i, ++j) - { - if (!OPT_expression_equal2(tdbb, csb, **i, **j, stream)) - return false; - } - - return true; - } - - break; + return exprNode1->expressionEqual(tdbb, csb, exprNode2, stream); } - case nod_add: - case nod_multiply: - case nod_add2: - case nod_multiply2: - case nod_equiv: - case nod_eql: - case nod_neq: - case nod_and: - case nod_or: - // A+B is equivalent to B+A, ditto A*B==B*A - // Note: If one expression is A+B+C, but the other is B+C+A we won't - // necessarily match them. - if (OPT_expression_equal2(tdbb, csb, node1->nod_arg[0], node2->nod_arg[1], stream) && - OPT_expression_equal2(tdbb, csb, node1->nod_arg[1], node2->nod_arg[0], stream)) - { - return true; - } - // Fall into ... - case nod_subtract: - case nod_divide: - case nod_subtract2: - case nod_divide2: - - // TODO match A > B to B <= A, etc - case nod_gtr: - case nod_geq: - case nod_leq: - case nod_lss: - if (OPT_expression_equal2(tdbb, csb, node1->nod_arg[0], node2->nod_arg[0], stream) && - OPT_expression_equal2(tdbb, csb, node1->nod_arg[1], node2->nod_arg[1], stream)) - { - return true; - } - break; - case nod_rec_version: case nod_dbkey: if (node1->nod_arg[0] == node2->nod_arg[0]) @@ -519,147 +307,77 @@ break; case nod_field: - { - const USHORT fld_stream = (USHORT)(IPTR) node2->nod_arg[e_fld_stream]; - if ((node1->nod_arg[e_fld_id] == node2->nod_arg[e_fld_id]) && fld_stream == stream) - { - return true; - } - } - break; + { + const USHORT fld_stream = (USHORT)(IPTR) node2->nod_arg[e_fld_stream]; + return (node1->nod_arg[e_fld_id] == node2->nod_arg[e_fld_id]) && fld_stream == stream; + } case nod_literal: - { - dsc desc1, desc2; + { + dsc desc1, desc2; - CMP_get_desc(tdbb, csb, node1, &desc1); - CMP_get_desc(tdbb, csb, node2, &desc2); + CMP_get_desc(tdbb, csb, node1, &desc1); + CMP_get_desc(tdbb, csb, node2, &desc2); - if (DSC_EQUIV(&desc1, &desc2, true) && - !memcmp(desc1.dsc_address, desc2.dsc_address, desc1.dsc_length)) - { - return true; - } - } - break; + return DSC_EQUIV(&desc1, &desc2, true) && + !memcmp(desc1.dsc_address, desc2.dsc_address, desc1.dsc_length); + } case nod_null: - case nod_user_name: - case nod_current_role: - case nod_current_time: - case nod_current_date: - case nod_current_timestamp: return true; - case nod_between: - case nod_like: - case nod_similar: - case nod_missing: - case nod_any: - case nod_ansi_any: - case nod_ansi_all: - case nod_not: - case nod_unique: - - case nod_value_if: case nod_substr: - case nod_trim: + if (node1->nod_count != node2->nod_count) + return false; + + for (int i = 0; i < node1->nod_count; ++i) { - if (node1->nod_count != node2->nod_count) - { + if (!OPT_expression_equal2(tdbb, csb, node1->nod_arg[i], node2->nod_arg[i], stream)) return false; - } - for (int i = 0; i < node1->nod_count; ++i) - { - if (!OPT_expression_equal2(tdbb, csb, node1->nod_arg[i], node2->nod_arg[i], stream)) - { - return false; - } - } - return true; } - break; - case nod_gen_id: - case nod_gen_id2: - if (node1->nod_arg[e_gen_id] == node2->nod_arg[e_gen_id]) - { - return true; - } - break; + return true; - case nod_negate: - case nod_internal_info: - if (OPT_expression_equal2(tdbb, csb, node1->nod_arg[0], node2->nod_arg[0], stream)) - { - return true; - } - break; - - case nod_upcase: - case nod_lowcase: - if (OPT_expression_equal2(tdbb, csb, node1->nod_arg[0], node2->nod_arg[0], stream)) - { - return true; - } - break; - case nod_cast: - { - dsc desc1, desc2; + { + dsc desc1, desc2; - CMP_get_desc(tdbb, csb, node1, &desc1); - CMP_get_desc(tdbb, csb, node2, &desc2); + CMP_get_desc(tdbb, csb, node1, &desc1); + CMP_get_desc(tdbb, csb, node2, &desc2); - if (DSC_EQUIV(&desc1, &desc2, true) && - OPT_expression_equal2(tdbb, csb, node1->nod_arg[e_cast_source], - node2->nod_arg[e_cast_source], stream)) - { - return true; - } - } - break; + return DSC_EQUIV(&desc1, &desc2, true) && + OPT_expression_equal2(tdbb, csb, node1->nod_arg[e_cast_source], + node2->nod_arg[e_cast_source], stream); + } case nod_extract: - if (node1->nod_arg[e_extract_part] == node2->nod_arg[e_extract_part] && + return node1->nod_arg[e_extract_part] == node2->nod_arg[e_extract_part] && OPT_expression_equal2(tdbb, csb, node1->nod_arg[e_extract_value], - node2->nod_arg[e_extract_value], stream)) - { - return true; - } - break; + node2->nod_arg[e_extract_value], stream); case nod_strlen: - if (node1->nod_arg[e_strlen_type] == node2->nod_arg[e_strlen_type] && + return node1->nod_arg[e_strlen_type] == node2->nod_arg[e_strlen_type] && OPT_expression_equal2(tdbb, csb, node1->nod_arg[e_strlen_value], - node2->nod_arg[e_strlen_value], stream)) - { - return true; - } - break; + node2->nod_arg[e_strlen_value], stream); case nod_list: - { - jrd_nod* const* ptr1 = node1->nod_arg; - jrd_nod* const* ptr2 = node2->nod_arg; + { + jrd_nod* const* ptr1 = node1->nod_arg; + jrd_nod* const* ptr2 = node2->nod_arg; - if (node1->nod_count != node2->nod_count) - { - return false; - } + if (node1->nod_count != node2->nod_count) + return false; - ULONG count = node1->nod_count; + ULONG count = node1->nod_count; - while (count--) - { - if (!OPT_expression_equal2(tdbb, csb, *ptr1++, *ptr2++, stream)) - { - return false; - } - } + while (count--) + { + if (!OPT_expression_equal2(tdbb, csb, *ptr1++, *ptr2++, stream)) + return false; + } - return true; - } + return true; + } // AB: New nodes has to be added @@ -704,32 +422,6 @@ } -jrd_nod* OPT_make_binary_node(nod_t type, jrd_nod* arg1, jrd_nod* arg2, bool flag) -{ -/************************************** - * - * m a k e _ b i n a r y _ n o d e - * - ************************************** - * - * Functional description - * Make a binary node. - * - **************************************/ - thread_db* tdbb = JRD_get_thread_data(); - DEV_BLKCHK(arg1, type_nod); - DEV_BLKCHK(arg2, type_nod); - jrd_nod* node = PAR_make_node(tdbb, 2); - node->nod_type = type; - node->nod_arg[0] = arg1; - node->nod_arg[1] = arg2; - if (flag) { - node->nod_flags |= nod_comparison; - } - return node; -} - - string OPT_make_alias(thread_db* tdbb, const CompilerScratch* csb, const CompilerScratch::csb_repeat* base_tail) { @@ -969,8 +661,8 @@ OptimizerRetrieval::OptimizerRetrieval(MemoryPool& p, OptimizerBlk* opt, SSHORT streamNumber, bool outer, - bool inner, jrd_nod** sortNode) : - pool(p), alias(p), indexScratches(p), inversionCandidates(p) + bool inner, SortNode** sortNode) + : pool(p), alias(p), indexScratches(p), inversionCandidates(p) { /************************************** * @@ -1023,8 +715,8 @@ } } -jrd_nod* OptimizerRetrieval::composeInversion(jrd_nod* node1, jrd_nod* node2, - nod_t node_type) const +InversionNode* OptimizerRetrieval::composeInversion(InversionNode* node1, InversionNode* node2, + InversionNode::Type node_type) const { /************************************** * @@ -1038,35 +730,32 @@ * **************************************/ - if (!node2) { + if (!node2) return node1; - } - if (!node1) { + if (!node1) return node2; - } - if (node_type == nod_bit_or) + if (node_type == InversionNode::TYPE_OR) { - if ((node1->nod_type == nod_index) && - (node2->nod_type == nod_index) && - (reinterpret_cast<IndexRetrieval*>(node1->nod_arg[e_idx_retrieval])->irb_index == - reinterpret_cast<IndexRetrieval*>(node2->nod_arg[e_idx_retrieval])->irb_index)) + if (node1->type == InversionNode::TYPE_INDEX && + node2->type == InversionNode::TYPE_INDEX && + node1->retrieval->irb_index == node2->retrieval->irb_index) { - node_type = nod_bit_in; + node_type = InversionNode::TYPE_IN; } - else if ((node1->nod_type == nod_bit_in) && - (node2->nod_type == nod_index) && - (reinterpret_cast<IndexRetrieval*>(node1->nod_arg[1]->nod_arg[e_idx_retrieval])->irb_index == - reinterpret_cast<IndexRetrieval*>(node2->nod_arg[e_idx_retrieval])->irb_index)) + else if (node1->type == InversionNode::TYPE_IN && + node2->type == InversionNode::TYPE_INDEX && + node1->node2->retrieval->irb_index == node2->retrieval->irb_index) { - node_type = nod_bit_in; + node_type = InversionNode::TYPE_IN; } } - return OPT_make_binary_node(node_type, node1, node2, false); + return FB_NEW(pool) InversionNode(node_type, node1, node2); } + void OptimizerRetrieval::findDependentFromStreams(jrd_nod* node, SortedStreamList* streamList) const { /************************************** @@ -1081,51 +770,24 @@ // Recurse thru interesting sub-nodes - if (node->nod_type == nod_procedure) + if (node->nod_type == nod_class_exprnode_jrd) { - jrd_nod* const inputs = node->nod_arg[e_prc_inputs]; - if (inputs) - { - fb_assert(inputs->nod_type == nod_asn_list); - jrd_nod* const* ptr = inputs->nod_arg; - for (const jrd_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++) - { - findDependentFromStreams(*ptr, streamList); - } - } + ExprNode* exprNode = reinterpret_cast<ExprNode*>(node->nod_arg[0]); + exprNode->findDependentFromStreams(this, streamList); } - else if (node->nod_type == nod_union) + else if (node->nod_type == nod_class_recsrcnode_jrd) { - jrd_nod* const clauses = node->nod_arg[e_uni_clauses]; - jrd_nod* const* ptr = clauses->nod_arg; - for (const jrd_nod* const* const end = ptr + clauses->nod_count; ptr < end; ptr += 2) - { - findDependentFromStreams(*ptr, streamList); - } + reinterpret_cast<RecordSourceNode*>(node->nod_arg[0])->findDependentFromStreams( + this, streamList); } - else if (node->nod_type == nod_class_exprnode_jrd) - { - ExprNode* exprNode = reinterpret_cast<ExprNode*>(node->nod_arg[0]); - - for (NestConst<NestConst<jrd_nod> >* i = exprNode->jrdChildNodes.begin(); - i != exprNode->jrdChildNodes.end(); ++i) - { - findDependentFromStreams(**i, streamList); - } - } else { jrd_nod* const* ptr = node->nod_arg; + for (const jrd_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++) - { findDependentFromStreams(*ptr, streamList); - } } - RecordSelExpr* rse; - jrd_nod* sub; - jrd_nod* value; - switch (node->nod_type) { case nod_field: @@ -1136,9 +798,8 @@ (csb->csb_rpt[fieldStream].csb_flags & csb_active) && !(csb->csb_rpt[fieldStream].csb_flags & csb_trigger)) { - if (!streamList->exist(fieldStream)) { + if (!streamList->exist(fieldStream)) streamList->add(fieldStream); - } } return; } @@ -1180,67 +841,26 @@ case nod_total: case nod_count: case nod_from: - if (sub = node->nod_arg[e_stat_default]) { + { + jrd_nod* sub; + + if (sub = node->nod_arg[e_stat_default]) findDependentFromStreams(sub, streamList); - } - rse = (RecordSelExpr*) node->nod_arg[e_stat_rse]; - value = node->nod_arg[e_stat_value]; - break; - case nod_rse: - rse = (RecordSelExpr*) node; - value = NULL; - break; + fb_assert(node->nod_arg[e_stat_rse]->nod_type == nod_class_recsrcnode_jrd); + RseNode* rse = reinterpret_cast<RseNode*>(node->nod_arg[e_stat_rse]->nod_arg[0]); - case nod_aggregate: - rse = (RecordSelExpr*) node->nod_arg[e_agg_rse]; - rse->rse_sorted = node->nod_arg[e_agg_group]; - value = NULL; - break; + rse->findDependentFromStreams(this, streamList); - case nod_window: - rse = (RecordSelExpr*) node->nod_arg[e_win_rse]; - value = NULL; - break; + jrd_nod* value = node->nod_arg[e_stat_value]; - default: - return; - } + // Check value expression, if any + if (value) + findDependentFromStreams(value, streamList); - // Node is a record selection expression. - if (sub = rse->rse_first) { - findDependentFromStreams(sub, streamList); + break; + } } - - if (sub = rse->rse_skip) { - findDependentFromStreams(sub, streamList); - } - - if (sub = rse->rse_boolean) { - findDependentFromStreams(sub, streamList); - } - - if (sub = rse->rse_sorted) { - findDependentFromStreams(sub, streamList); - } - - if (sub = rse->rse_projection) { - findDependentFromStreams(sub, streamList); - } - - jrd_nod* const* ptr; - const jrd_nod* const* end; - for (ptr = rse->rse_relation, end = ptr + rse->rse_count; ptr < end; ptr++) - { - findDependentFromStreams(*ptr, streamList); - } - - // Check value expression, if any - if (value) { - findDependentFromStreams(value, streamList); - } - - return; } const string& OptimizerRetrieval::getAlias() @@ -1289,13 +909,15 @@ // Check for any DB_KEY comparisons for (OptimizerBlk::opt_conjunct* tail = opt_begin; tail < opt_end; tail++) { - if (tail->opt_conjunct_flags & opt_conjunct_matched) { + if (tail->opt_conjunct_flags & opt_conjunct_matched) continue; - } - jrd_nod* const node = tail->opt_conjunct_node; + + BoolExprNode* const node = tail->opt_conjunct_node; + if (!(tail->opt_conjunct_flags & opt_conjunct_used) && node) { invCandidate = matchDbKey(node); + if (invCandidate) { invCandidate->boolean = node; @@ -1304,14 +926,17 @@ } } - // First, handle "AND" comparisons (all nodes except nod_or) + // First, handle "AND" comparisons (all nodes except OR) for (OptimizerBlk::opt_conjunct* tail = opt_begin; tail < opt_end; tail++) { - if (tail->opt_conjunct_flags & opt_conjunct_matched) { + if (tail->opt_conjunct_flags & opt_conjunct_matched) continue; - } - jrd_nod* const node = tail->opt_conjunct_node; - if (!(tail->opt_conjunct_flags & opt_conjunct_used) && node && (node->nod_type != nod_or)) + + BoolExprNode* const node = tail->opt_conjunct_node; + BinaryBoolNode* booleanNode = node->as<BinaryBoolNode>(); + + if (!(tail->opt_conjunct_flags & opt_conjunct_used) && node && + (!booleanNode || booleanNode->blrOp != blr_or)) { matchOnIndexes(&indexScratches, node, 1); } @@ -1319,20 +944,23 @@ getInversionCandidates(&inversions, &indexScratches, 1); - if (sort && rsb) { + if (sort && rsb) *rsb = generateNavigation(); - } // Second, handle "OR" comparisons for (OptimizerBlk::opt_conjunct* tail = opt_begin; tail < opt_end; tail++) { - if (tail->opt_conjunct_flags & opt_conjunct_matched) { + if (tail->opt_conjunct_flags & opt_conjunct_matched) continue; - } - jrd_nod* const node = tail->opt_conjunct_node; - if (!(tail->opt_conjunct_flags & opt_conjunct_used) && node && (node->nod_type == nod_or)) + + BoolExprNode* const node = tail->opt_conjunct_node; + BinaryBoolNode* booleanNode = node->as<BinaryBoolNode>(); + + if (!(tail->opt_conjunct_flags & opt_conjunct_used) && node && + (booleanNode && booleanNode->blrOp == blr_or)) { invCandidate = matchOnIndexes(&indexScratches, node, 1); + if (invCandidate) { invCandidate->boolean = node; @@ -1351,9 +979,7 @@ // Clean up inversion list InversionCandidate** inversion = inversions.begin(); for (size_t i = 0; i < inversions.getCount(); i++) - { delete inversion[i]; - } } if (!invCandidate) @@ -1380,13 +1006,15 @@ for (const OptimizerBlk::opt_conjunct* tail = optimizer->opt_conjuncts.begin(); tail < optimizer->opt_conjuncts.end(); tail++) { - jrd_nod* const node = tail->opt_conjunct_node; + BoolExprNode* const node = tail->opt_conjunct_node; if (!(tail->opt_conjunct_flags & opt_conjunct_used) && - OPT_computable(csb, node, stream, false, true) && + node->computable(csb, stream, false, true) && !invCandidate->matches.exist(node)) { - const double factor = (node->nod_type == nod_eql) ? + const ComparativeBoolNode* cmpNode = node->as<ComparativeBoolNode>(); + + const double factor = (cmpNode && cmpNode->blrOp == blr_eql) ? REDUCE_SELECTIVITY_FACTOR_EQUALITY : REDUCE_SELECTIVITY_FACTOR_INEQUALITY; invCandidate->selectivity *= factor; } @@ -1394,25 +1022,24 @@ // Add the streams where this stream is depending on. for (size_t i = 0; i < invCandidate->matches.getCount(); i++) - { - findDependentFromStreams(invCandidate->matches[i], &invCandidate->dependentFromStreams); - } + invCandidate->matches[i]->findDependentFromStreams(this, &invCandidate->dependentFromStreams); if (setConjunctionsMatched) { - SortedArray<jrd_nod*> matches; + SortedArray<BoolExprNode*> matches; + // AB: Putting a unsorted array in a sorted array directly by join isn't // very safe at the moment, but in our case Array holds a sorted list. // However SortedArray class should be updated to handle join right! + matches.join(invCandidate->matches); + for (OptimizerBlk::opt_conjunct* tail = opt_begin; tail < opt_end; tail++) { if (!(tail->opt_conjunct_flags & opt_conjunct_used)) { if (matches.exist(tail->opt_conjunct_node)) - { tail->opt_conjunct_flags |= opt_conjunct_matched; - } } } } @@ -1438,10 +1065,9 @@ **************************************/ fb_assert(sort); - jrd_nod* sortPtr = *sort; - if (!sortPtr) { + SortNode* sortPtr = *sort; + if (!sortPtr) return NULL; - } size_t i = 0; for (; i < indexScratches.getCount(); ++i) @@ -1454,9 +1080,8 @@ // sort--note that in the case where the first field is unique, this // could be optimized, since the sort will be performed correctly by // navigating on a unique index on the first field--deej - if (sortPtr->nod_count > idx->idx_count) { + if (sortPtr->expressions.getCount() > idx->idx_count) continue; - } // if the user-specified access plan for this request didn't // mention this index, forget it @@ -1470,7 +1095,7 @@ // an expression index if (idx->idx_flags & idx_expressn) { - if (sortPtr->nod_count != 1) + if (sortPtr->expressions.getCount() != 1) continue; } @@ -1479,10 +1104,17 @@ bool usableIndex = true; index_desc::idx_repeat* idx_tail = idx->idx_rpt; - jrd_nod* const* ptr = sortPtr->nod_arg; - for (const jrd_nod* const* const end = ptr + sortPtr->nod_count; ptr < end; ptr++, idx_tail++) + NestConst<jrd_nod>* ptr = sortPtr->expressions.begin(); + const bool* descending = sortPtr->descending.begin(); + const int* nullOrder = sortPtr->nullOrder.begin(); + + for (const NestConst<jrd_nod>* const end = sortPtr->expressions.end(); + ptr != end; + ++ptr, ++descending, ++nullOrder, ++idx_tail) { + jrd_nod* node = *ptr; + if (idx->idx_flags & idx_expressn) { if (!OPT_expression_equal(tdbb, csb, idx, node, stream)) @@ -1499,12 +1131,10 @@ break; } - if ((ptr[sortPtr->nod_count] && !(idx->idx_flags & idx_descending)) || - (!ptr[sortPtr->nod_count] && (idx->idx_flags & idx_descending)) || - ((reinterpret_cast<IPTR>(ptr[2 * sortPtr->nod_count]) == rse_nulls_first && - ptr[sortPtr->nod_count]) || - (reinterpret_cast<IPTR>(ptr[2 * sortPtr->nod_count]) == rse_nulls_last && - !ptr[sortPtr->nod_count]))) + if ((*descending && !(idx->idx_flags & idx_descending)) || + (!*descending && (idx->idx_flags & idx_descending)) || + ((*nullOrder == rse_nulls_first && *descending) || + (*nullOrder == rse_nulls_last && !*descending))) { usableIndex = false; break; @@ -1533,8 +1163,7 @@ // ASF: We currently can't use non-unique index for GROUP BY and DISTINCT with // multi-level and insensitive collation. In NAV, keys are verified with memcmp // but there we don't know length of each level. - if ((sortPtr->nod_flags & nod_unique_sort) && - (tt->getFlags() & TEXTTYPE_SEPARATE_UNIQUE)) + if (sortPtr->unique && (tt->getFlags() & TEXTTYPE_SEPARATE_UNIQUE)) { usableIndex = false; break; @@ -1556,7 +1185,7 @@ idx->idx_runtime_flags |= idx_navigate; indexScratches[i].utilized = true; - jrd_nod* const index_node = makeIndexScanNode(&indexScratches[i]); + InversionNode* const index_node = makeIndexScanNode(&indexScratches[i]); const USHORT key_length = ROUNDUP(BTR_key_length(tdbb, relation, idx), sizeof(SLONG)); return FB_NEW(*tdbb->getDefaultPool()) IndexTableScan(csb, getAlias(), stream, index_node, key_length); @@ -1616,8 +1245,9 @@ const double cardinality = csb->csb_rpt[stream].csb_cardinality; // Walk through indexes to calculate selectivity / candidate - Array<jrd_nod*> matches; + Array<BoolExprNode*> matches; size_t i = 0; + for (i = 0; i < fromIndexScratches->getCount(); i++) { IndexScratch& scratch = (*fromIndexScratches)[i]; @@ -1626,17 +1256,21 @@ scratch.lowerCount = 0; scratch.upperCount = 0; scratch.nonFullMatchedSegments = MAX_INDEX_SEGMENTS + 1; + if (scratch.candidate) { matches.clear(); scratch.selectivity = MAXIMUM_SELECTIVITY; + bool unique = false; + for (int j = 0; j < scratch.idx->idx_count; j++) { IndexScratchSegment* segment = scratch.segments[j]; - if (segment->scope == scope) { + + if (segment->scope == scope) scratch.scopeCandidate = true; - } + // Check if this is the last usable segment if (((segment->scanType == segmentScanEqual) || (segment->scanType == segmentScanEquivalent) || @@ -1684,6 +1318,7 @@ // estimate the selectivity double selectivity = scratch.selectivity; double factor = 1; + switch (segment->scanType) { case segmentScanBetween: @@ -1741,6 +1376,7 @@ // For a non-unique one, assume 1/10 of the maximum selectivity, so that // at least some indexes could be chosen by the optimizer. double selectivity = scratch.selectivity; + if (selectivity <= 0) { if (unique && cardinality) @@ -1765,11 +1401,13 @@ invCandidate->indexes = 1; invCandidate->scratch = &scratch; invCandidate->matches.join(matches); + for (size_t k = 0; k < invCandidate->matches.getCount(); k++) { - findDependentFromStreams(invCandidate->matches[k], - &invCandidate->dependentFromStreams); + invCandidate->matches[k]->findDependentFromStreams(this, + &invCandidate->dependentFromStreams); } + invCandidate->dependencies = (int) invCandidate->dependentFromStreams.getCount(); inversions->add(invCandidate); } @@ -1794,9 +1432,7 @@ if (dbkey->nod_type == nod_dbkey) { if ((USHORT)(IPTR) dbkey->nod_arg[0] == stream) - { return dbkey; - } *position = *position + 1; return NULL; @@ -1807,23 +1443,21 @@ if (concatNode) { jrd_nod* dbkey_temp = findDbKey(concatNode->arg1, stream, position); + if (dbkey_temp) - { return dbkey_temp; - } dbkey_temp = findDbKey(concatNode->arg2, stream, position); + if (dbkey_temp) - { return dbkey_temp; - } } return NULL; } -jrd_nod* OptimizerRetrieval::makeIndexNode(const index_desc* idx) const +InversionNode* OptimizerRetrieval::makeIndexNode(const index_desc* idx) const { /************************************** * @@ -1846,21 +1480,19 @@ Resource::rsc_index, idx->idx_id); } - jrd_nod* node = PAR_make_node(tdbb, e_idx_length); - node->nod_type = nod_index; - node->nod_count = 0; - IndexRetrieval* retrieval = FB_NEW_RPT(pool, idx->idx_count * 2) IndexRetrieval(); - node->nod_arg[e_idx_retrieval] = (jrd_nod*) retrieval; retrieval->irb_index = idx->idx_id; memcpy(&retrieval->irb_desc, idx, sizeof(retrieval->irb_desc)); - if (csb) { - node->nod_impure = CMP_impure(csb, sizeof(impure_inversion)); - } + + InversionNode* node = FB_NEW(pool) InversionNode(retrieval); + + if (csb) + node->impure = CMP_impure(csb, sizeof(impure_inversion)); + return node; } -jrd_nod* OptimizerRetrieval::makeIndexScanNode(IndexScratch* indexScratch) const +InversionNode* OptimizerRetrieval::makeIndexScanNode(IndexScratch* indexScratch) const { /************************************** * @@ -1873,14 +1505,13 @@ * **************************************/ - if (!createIndexScanNodes) { + if (!createIndexScanNodes) return NULL; - } // Allocate both a index retrieval node and block. index_desc* idx = indexScratch->idx; - jrd_nod* node = makeIndexNode(idx); - IndexRetrieval* retrieval = (IndexRetrieval*) node->nod_arg[e_idx_retrieval]; + InversionNode* node = makeIndexNode(idx); + IndexRetrieval* retrieval = node->retrieval; retrieval->irb_relation = relation; // Pick up lower bound segment values @@ -1902,6 +1533,7 @@ int i = 0; bool ignoreNullsOnScan = true; IndexScratchSegment** segment = indexScratch->segments.begin(); + for (i = 0; i < MAX(indexScratch->lowerCount, indexScratch->upperCount); i++) { if (segment[i]->scanType == segmentScanMissing) @@ -1913,19 +1545,19 @@ } else { - if (i < indexScratch->lowerCount) { + if (i < indexScratch->lowerCount) *lower++ = segment[i]->lowerValue; - } - if (i < indexScratch->upperCount) { + + if (i < indexScratch->upperCount) *upper++ = segment[i]->upperValue; - } - if (segment[i]->scanType == segmentScanEquivalent) { + + if (segment[i]->scanType == segmentScanEquivalent) ignoreNullsOnScan = false; - } } } i = MAX(indexScratch->lowerCount, indexScratch->upperCount) - 1; + if (i >= 0) { if (segment[i]->scanType == segmentScanStarting) @@ -1941,8 +1573,11 @@ for (IndexScratchSegment** tail = indexScratch->segments.begin(); tail != indexScratch->segments.end() && ((*tail)->lowerValue || (*tail)->upperValue); ++tail) { + ComparativeBoolNode* cmpNode = (*tail)->matches[0]->as<ComparativeBoolNode>(); + fb_assert(cmpNode); + dsc dsc0; - CMP_get_desc(tdbb, csb, (*tail)->matches[0]->nod_arg[0], &dsc0); + CMP_get_desc(tdbb, csb, cmpNode->arg1.getObject(), &dsc0); // ASF: "dsc0.dsc_ttype() > ttype_last_internal" is to avoid recursion // when looking for charsets/collations @@ -1981,15 +1616,14 @@ // which requires NULLs to be found in the index. // A second exception is when this index is used for navigation. if (ignoreNullsOnScan && !(idx->idx_runtime_flags & idx_navigate)) - { retrieval->irb_generic |= irb_ignore_null_value_key; - } // Check to see if this is really an equality retrieval if (retrieval->irb_lower_count == retrieval->irb_upper_count) { retrieval->irb_generic |= irb_equality; segment = indexScratch->segments.begin(); + for (i = 0; i < retrieval->irb_lower_count; i++) { if (segment[i]->lowerValue != segment[i]->upperValue) @@ -2003,15 +1637,13 @@ // If we are matching less than the full index, this is a partial match if (idx->idx_flags & idx_descending) { - if (retrieval->irb_lower_count < idx->idx_count) { + if (retrieval->irb_lower_count < idx->idx_count) retrieval->irb_generic |= irb_partial; - } } else { - if (retrieval->irb_upper_count < idx->idx_count) { + if (retrieval->irb_upper_count < idx->idx_count) retrieval->irb_generic |= irb_partial; - } } // mark the index as utilized for the purposes of this compile @@ -2083,11 +1715,10 @@ } // The matches returned in this inversion are always sorted. - SortedArray<jrd_nod*> matches; + SortedArray<BoolExprNode*> matches; for (i = 0; i < inversions->getCount(); i++) { - // Initialize vars before walking through candidates InversionCandidate* bestCandidate = NULL; bool restartLoop = false; @@ -2101,15 +1732,14 @@ // we can make the inversion and return it. if (currentInv->unique && currentInv->dependencies) { - if (!invCandidate) { + if (!invCandidate) invCandidate = FB_NEW(pool) InversionCandidate(pool); - } - if (!currentInv->inversion && currentInv->scratch) { + + if (!currentInv->inversion && currentInv->scratch) invCandidate->inversion = makeIndexScanNode(currentInv->scratch); - } - else { + else invCandidate->inversion = currentInv->inversion; - } + invCandidate->unique = currentInv->unique; invCandidate->selectivity = currentInv->selectivity; invCandidate->cost = currentInv->cost; @@ -2118,16 +1748,16 @@ invCandidate->matchedSegments = currentInv->matchedSegments; invCandidate->dependencies = currentInv->dependencies; matches.clear(); + for (size_t j = 0; j < currentInv->matches.getCount(); j++) { - if (!matches.exist(currentInv->matches[j])) { + if (!matches.exist(currentInv->matches[j])) matches.add(currentInv->matches[j]); - } } + invCandidate->matches.join(matches); - if (acceptAll) { + if (acceptAll) continue; - } return invCandidate; } @@ -2341,13 +1971,14 @@ if (!bestCandidate->inversion && bestCandidate->scratch) { invCandidate->inversion = composeInversion(invCandidate->inversion, - makeIndexScanNode(bestCandidate->scratch), nod_bit_and); + makeIndexScanNode(bestCandidate->scratch), InversionNode::TYPE_AND); } else { invCandidate->inversion = composeInversion(invCandidate->inversion, - bestCandidate->inversion, nod_bit_and); + bestCandidate->inversion, InversionNode::TYPE_AND); } + invCandidate->unique = (invCandidate->unique || bestCandidate->unique); invCandidate->selectivity = totalSelectivity; invCandidate->cost += bestCandidate->cost; @@ -2356,19 +1987,20 @@ invCandidate->matchedSegments = MAX(bestCandidate->matchedSegments, invCandidate->matchedSegments); invCandidate->dependencies += bestCandidate->dependencies; + for (size_t j = 0; j < bestCandidate->matches.getCount(); j++) { - if (!matches.exist(bestCandidate->matches[j])) { + if (!matches.exist(bestCandidate->matches[j])) matches.add(bestCandidate->matches[j]); - } } + if (bestCandidate->boolean) { - if (!matches.exist(bestCandidate->boolean)) { + if (!matches.exist(bestCandidate->boolean)) matches.add(bestCandidate->boolean); - } } } + if (invCandidate->unique) { // Single unique full equal match is enough @@ -2394,7 +2026,8 @@ return invCandidate; } -bool OptimizerRetrieval::matchBoolean(IndexScratch* indexScratch, jrd_nod* boolean, USHORT scope) const +bool OptimizerRetrieval::matchBoolean(IndexScratch* indexScratch, BoolExprNode* boolean, + USHORT scope) const { /************************************** * @@ -2405,12 +2038,32 @@ * Functional description * **************************************/ + ComparativeBoolNode* cmpNode = boolean->as<ComparativeBoolNode>(); + MissingBoolNode* missingNode = boolean->as<MissingBoolNode>(); + NotBoolNode* notNode = boolean->as<NotBoolNode>(); + RseBoolNode* rseNode = boolean->as<RseBoolNode>(); bool forward = true; + jrd_nod* value = NULL; + jrd_nod* match = NULL; - jrd_nod* match = boolean->nod_arg[0]; - jrd_nod* value = (boolean->nod_count < 2) ? NULL : boolean->nod_arg[1]; - jrd_nod* value2 = (boolean->nod_type == nod_between) ? boolean->nod_arg[2] : NULL; + if (cmpNode) + { + match = cmpNode->arg1; + value = cmpNode->arg2; + } + else if (missingNode) + match = missingNode->arg; + else if (notNode) + return false; + else if (rseNode) + match = rseNode->rse; + else + { + fb_assert(false); + } + jrd_nod* value2 = (cmpNode && cmpNode->blrOp == blr_between) ? cmpNode->arg3 : NULL; + if (indexScratch->idx->idx_flags & idx_expressn) { // see if one side or the other is matchable to the index expression @@ -2420,12 +2073,13 @@ if (!OPT_expression_equal(tdbb, csb, indexScratch->idx, match, stream) || (value && !OPT_computable(csb, value, stream, true, false))) { - if (boolean->nod_type != nod_starts && value && + if ((!cmpNode || cmpNode->blrOp != blr_starting) && value && OPT_expression_equal(tdbb, csb, indexScratch->idx, value, stream) && OPT_computable(csb, match, stream, true, false)) { - match = boolean->nod_arg[1]; - value = boolean->nod_arg[0]; + jrd_nod* temp = match; + match = value; + value = temp; forward = false; } else @@ -2441,14 +2095,17 @@ (USHORT)(IPTR) match->nod_arg[e_fld_stream] != stream || (value && !OPT_computable(csb, value, stream, true, false))) { + jrd_nod* temp = match; match = value; - value = boolean->nod_arg[0]; + value = temp; + if (!match || match->nod_type != nod_field || (USHORT)(IPTR) match->nod_arg[e_fld_stream] != stream || !OPT_computable(csb, value, stream, true, false)) { return false; } + forward = false; } } @@ -2501,156 +2158,153 @@ const bool isDesc = (indexScratch->idx->idx_flags & idx_descending); int count = 0; IndexScratchSegment** segment = indexScratch->segments.begin(); + for (int i = 0; i < indexScratch->idx->idx_count; ... [truncated message content] |
From: <ale...@us...> - 2010-10-13 05:51:02
|
Revision: 51664 http://firebird.svn.sourceforge.net/firebird/?rev=51664&view=rev Author: alexpeshkoff Date: 2010-10-13 05:50:53 +0000 (Wed, 13 Oct 2010) Log Message: ----------- More lost files Added Paths: ----------- firebird/trunk/src/jrd/RecordSourceNodes.cpp firebird/trunk/src/jrd/RecordSourceNodes.h Added: firebird/trunk/src/jrd/RecordSourceNodes.cpp =================================================================== --- firebird/trunk/src/jrd/RecordSourceNodes.cpp (rev 0) +++ firebird/trunk/src/jrd/RecordSourceNodes.cpp 2010-10-13 05:50:53 UTC (rev 51664) @@ -0,0 +1,2485 @@ +/* + * The contents of this file are subject to the Interbase Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy + * of the License at http://www.Inprise.com/IPL.html + * + * Software distributed under the License is distributed on an + * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express + * or implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code was created by Inprise Corporation + * and its predecessors. Portions created by Inprise Corporation are + * Copyright (C) Inprise Corporation. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * Adriano dos Santos Fernandes + */ + +#include "firebird.h" +#include "../jrd/common.h" +#include "../jrd/align.h" +#include "../jrd/RecordSourceNodes.h" +#include "../jrd/DataTypeUtil.h" +#include "../jrd/Optimizer.h" +#include "../jrd/recsrc/RecordSource.h" +#include "../dsql/BoolNodes.h" +#include "../dsql/ExprNodes.h" +#include "../jrd/btr_proto.h" +#include "../jrd/cmp_proto.h" +#include "../common/dsc_proto.h" +#include "../jrd/met_proto.h" +#include "../jrd/opt_proto.h" +#include "../jrd/par_proto.h" + +using namespace Firebird; +using namespace Jrd; + + +static MapNode* parseMap(thread_db* tdbb, CompilerScratch* csb, USHORT stream); +static SSHORT strcmpSpace(const char* p, const char* q); +static void processSource(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, + RecordSourceNode* source, BoolExprNode** boolean, RecordSourceNodeStack& stack); +static void processMap(thread_db* tdbb, CompilerScratch* csb, MapNode* map, Format** inputFormat); +static void genDeliverUnmapped(thread_db* tdbb, BoolExprNodeStack* deliverStack, MapNode* map, + BoolExprNodeStack* parentStack, UCHAR shellStream); +static void markIndices(CompilerScratch::csb_repeat* csbTail, SSHORT relationId); +static void sortIndicesBySelectivity(CompilerScratch::csb_repeat* csbTail); + + +//-------------------- + + +SortNode* SortNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + SortNode* newSort = FB_NEW(*tdbb->getDefaultPool()) SortNode(*tdbb->getDefaultPool()); + newSort->unique = unique; + + for (NestConst<jrd_nod>* i = expressions.begin(); i != expressions.end(); ++i) + newSort->expressions.add(copier.copy(tdbb, *i)); + + newSort->descending = descending; + newSort->nullOrder = nullOrder; + + return newSort; +} + +void SortNode::pass1(thread_db* tdbb, CompilerScratch* csb) +{ + for (NestConst<jrd_nod>* i = expressions.begin(); i != expressions.end(); ++i) + *i = CMP_pass1(tdbb, csb, *i); +} + +void SortNode::pass2(thread_db* tdbb, CompilerScratch* csb) +{ + for (NestConst<jrd_nod>* i = expressions.begin(); i != expressions.end(); ++i) + (*i)->nod_flags |= nod_value; + + for (NestConst<jrd_nod>* i = expressions.begin(); i != expressions.end(); ++i) + CMP_pass2(tdbb, csb, *i, NULL); +} + +bool SortNode::computable(CompilerScratch* csb, SSHORT stream, bool idx_use, + bool allowOnlyCurrentStream) +{ + for (NestConst<jrd_nod>* i = expressions.begin(); i != expressions.end(); ++i) + { + if (!OPT_computable(csb, *i, stream, idx_use, allowOnlyCurrentStream)) + return false; + } + + return true; +} + +void SortNode::findDependentFromStreams(const OptimizerRetrieval* optRet, + SortedStreamList* streamList) +{ + for (NestConst<jrd_nod>* i = expressions.begin(); i != expressions.end(); ++i) + optRet->findDependentFromStreams(*i, streamList); +} + + +//-------------------- + + +MapNode* MapNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + MapNode* newMap = FB_NEW(*tdbb->getDefaultPool()) MapNode(*tdbb->getDefaultPool()); + + for (NestConst<jrd_nod>* i = items.begin(); i != items.end(); ++i) + newMap->items.add(copier.copy(tdbb, *i)); + + return newMap; +} + +void MapNode::pass1(thread_db* tdbb, CompilerScratch* csb) +{ + for (NestConst<jrd_nod>* i = items.begin(); i != items.end(); ++i) + *i = CMP_pass1(tdbb, csb, *i); +} + +void MapNode::pass2(thread_db* tdbb, CompilerScratch* csb) +{ + for (NestConst<jrd_nod>* i = items.begin(); i != items.end(); ++i) + CMP_pass2(tdbb, csb, *i, NULL); +} + + +//-------------------- + + +// Parse a relation reference. +RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* csb, + SSHORT blrOp, bool parseContext) +{ + SET_TDBB(tdbb); + + // Make a relation reference node + + RelationSourceNode* node = FB_NEW(*tdbb->getDefaultPool()) RelationSourceNode( + *tdbb->getDefaultPool()); + + // Find relation either by id or by name + string* aliasString = NULL; + MetaName name; + + switch (blrOp) + { + case blr_rid: + case blr_rid2: + { + const SSHORT id = csb->csb_blr_reader.getWord(); + + if (blrOp == blr_rid2) + { + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); + } + + if (!(node->relation = MET_lookup_relation_id(tdbb, id, false))) + name.printf("id %d", id); + + break; + } + + case blr_relation: + case blr_relation2: + { + PAR_name(csb, name); + + if (blrOp == blr_relation2) + { + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); + } + + node->relation = MET_lookup_relation(tdbb, name); + break; + } + + default: + fb_assert(false); + } + + if (!node->relation) + PAR_error(csb, Arg::Gds(isc_relnotdef) << Arg::Str(name), false); + + // if an alias was passed, store with the relation + + if (aliasString) + node->alias = stringDup(*tdbb->getDefaultPool(), *aliasString); + + // Scan the relation if it hasn't already been scanned for meta data + + if ((!(node->relation->rel_flags & REL_scanned) || (node->relation->rel_flags & REL_being_scanned)) && + ((node->relation->rel_flags & REL_force_scan) || !(csb->csb_g_flags & csb_internal))) + { + node->relation->rel_flags &= ~REL_force_scan; + MET_scan_relation(tdbb, node->relation); + } + else if (node->relation->rel_flags & REL_sys_triggers) + MET_parse_sys_trigger(tdbb, node->relation); + + // generate a stream for the relation reference, assuming it is a real reference + + if (parseContext) + { + node->stream = PAR_context(csb, &node->context); + fb_assert(node->stream <= MAX_STREAMS); + + csb->csb_rpt[node->stream].csb_relation = node->relation; + csb->csb_rpt[node->stream].csb_alias = aliasString; + + if (csb->csb_g_flags & csb_get_dependencies) + PAR_dependency(tdbb, csb, node->stream, (SSHORT) -1, ""); + } + else + delete aliasString; + + return node; +} + +RelationSourceNode* RelationSourceNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + if (!copier.remap) + BUGCHECK(221); // msg 221 (CMP) copy: cannot remap + + RelationSourceNode* newSource = FB_NEW(*tdbb->getDefaultPool()) RelationSourceNode( + *tdbb->getDefaultPool()); + + // Last entry in the remap contains the the original stream number. + // Get that stream number so that the flags can be copied + // into the newly created child stream. + + const int relativeStream = stream ? copier.remap[stream - 1] : stream; + newSource->stream = copier.csb->nextStream(); + copier.remap[stream] = (UCHAR) newSource->stream; + + newSource->context = context; + newSource->relation = relation; + newSource->view = view; + + CompilerScratch::csb_repeat* element = CMP_csb_element(copier.csb, newSource->stream); + element->csb_relation = (jrd_rel*) newSource->relation; + element->csb_view = newSource->view; + element->csb_view_stream = copier.remap[0]; + + /** If there was a parent stream no., then copy the flags + from that stream to its children streams. (Bug 10164/10166) + For e.g. + consider a view V1 with 2 streams + stream #1 from table T1 + stream #2 from table T2 + consider a procedure P1 with 2 streams + stream #1 from table X + stream #2 from view V1 + + During pass1 of procedure request, the engine tries to expand + all the views into their base tables. It creates a compiler + scratch block which initially looks like this + stream 1 -------- X + stream 2 -------- V1 + while expanding V1 the engine calls copy() with nod_relation. + A new stream 3 is created. Now the CompilerScratch looks like + stream 1 -------- X + stream 2 -------- V1 map [2,3] + stream 3 -------- T1 + After T1 stream has been created the flags are copied from + stream #1 because V1's definition said the original stream + number for T1 was 1. However since its being merged with + the procedure request, stream #1 belongs to a different table. + The flags should be copied from stream 2 i.e. V1. We can get + this info from variable remap. + + Since we didn't do this properly before, V1's children got + tagged with whatever flags X possesed leading to various + errors. + + We now store the proper stream no in relativeStream and + later use it to copy the flags. -Sudesh (03/05/99) + **/ + + copier.csb->csb_rpt[newSource->stream].csb_flags |= + copier.csb->csb_rpt[relativeStream].csb_flags & csb_no_dbkey; + + return newSource; +} + +void RelationSourceNode::ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const +{ + csb->csb_rpt[stream].csb_flags |= csb_no_dbkey; + const CompilerScratch::csb_repeat* tail = &csb->csb_rpt[stream]; + const jrd_rel* relation = tail->csb_relation; + + if (relation) + { + CMP_post_access(tdbb, csb, relation->rel_security_name, + (tail->csb_view) ? tail->csb_view->rel_id : (view ? view->rel_id : 0), + SCL_read, SCL_object_table, relation->rel_name); + } +} + +void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, + BoolExprNode** boolean, RecordSourceNodeStack& stack) +{ + stack.push(this); // Assume that the source will be used. Push it on the final stream stack. + + // We have a view or a base table; + // prepare to check protection of relation when a field in the stream of the + // relation is accessed. + + jrd_rel* const parentView = csb->csb_view; + const USHORT viewStream = csb->csb_view_stream; + + jrd_rel* relationView = relation; + CMP_post_resource(&csb->csb_resources, relationView, Resource::rsc_relation, relationView->rel_id); + view = parentView; + + CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream); + element->csb_view = parentView; + fb_assert(viewStream <= MAX_STREAMS); + element->csb_view_stream = (UCHAR) viewStream; + + // in the case where there is a parent view, find the context name + + if (parentView) + { + const ViewContexts& ctx = parentView->rel_view_contexts; + const USHORT key = context; + size_t pos; + + if (ctx.find(key, pos)) + { + element->csb_alias = FB_NEW(csb->csb_pool) + string(csb->csb_pool, ctx[pos]->vcx_context_name); + } + } + + // check for a view - if not, nothing more to do + + RseNode* viewRse = relationView->rel_view_rse; + if (!viewRse) + return; + + // we've got a view, expand it + + DEBUG; + stack.pop(); + UCHAR* map = CMP_alloc_map(tdbb, csb, stream); + + AutoSetRestore<USHORT> autoRemapVariable(&csb->csb_remap_variable, + (csb->csb_variables ? csb->csb_variables->count() : 0) + 1); + AutoSetRestore<jrd_rel*> autoView(&csb->csb_view, relationView); + AutoSetRestore<USHORT> autoViewStream(&csb->csb_view_stream, stream); + + // We don't expand the view in two cases: + // 1) If the view has a projection, sort, first/skip or explicit plan. + // 2) If it's part of an outer join. + + if (rse->rse_jointype || // viewRse->rse_jointype || ??? + viewRse->rse_sorted || viewRse->rse_projection || viewRse->rse_first || + viewRse->rse_skip || viewRse->rse_plan) + { + NodeCopier copier(csb, map); + RseNode* copy = viewRse->copy(tdbb, copier); + DEBUG; + copy->pass1(tdbb, csb, csb->csb_view); + stack.push(copy); + DEBUG; + return; + } + + // ASF: Below we start to do things when viewRse->rse_projection is not NULL. + // But we should never come here, as the code above returns in this case. + + // if we have a projection which we can bubble up to the parent rse, set the + // parent rse to our projection temporarily to flag the fact that we have already + // seen one so that lower-level views will not try to map their projection; the + // projection will be copied and correctly mapped later, but we don't have all + // the base streams yet + + if (viewRse->rse_projection) + rse->rse_projection = viewRse->rse_projection; + + // disect view into component relations + + NestConst<RecordSourceNode>* arg = viewRse->rse_relations.begin(); + for (const NestConst<RecordSourceNode>* const end = viewRse->rse_relations.end(); arg != end; ++arg) + { + // this call not only copies the node, it adds any streams it finds to the map + NodeCopier copier(csb, map); + RecordSourceNode* node = (*arg)->copy(tdbb, copier); + + // Now go out and process the base table itself. This table might also be a view, + // in which case we will continue the process by recursion. + processSource(tdbb, csb, rse, node, boolean, stack); + } + + // When there is a projection in the view, copy the projection up to the query RseNode. + // In order to make this work properly, we must remap the stream numbers of the fields + // in the view to the stream number of the base table. Note that the map at this point + // contains the stream numbers of the referenced relations, since it was added during the call + // to copy() above. After the copy() below, the fields in the projection will reference the + // base table(s) instead of the view's context (see bug #8822), so we are ready to context- + // recognize them in CMP_pass1() - that is, replace the field nodes with actual field blocks. + + if (viewRse->rse_projection) + { + NodeCopier copier(csb, map); + rse->rse_projection = viewRse->rse_projection->copy(tdbb, copier); + rse->rse_projection->pass1(tdbb, csb); + } + + // if we encounter a boolean, copy it and retain it by ANDing it in with the + // boolean on the parent view, if any + + if (viewRse->rse_boolean) + { + NodeCopier copier(csb, map); + BoolExprNode* node = viewRse->rse_boolean->copy(tdbb, copier); + + node = node->pass1(tdbb, csb); + + if (*boolean) + { + // The order of the nodes here is important! The + // boolean from the view must appear first so that + // it gets expanded first in pass1. + + BinaryBoolNode* andNode = FB_NEW(csb->csb_pool) BinaryBoolNode(csb->csb_pool, blr_and); + andNode->arg1 = node; + andNode->arg2 = *boolean; + + *boolean = andNode; + } + else + *boolean = node; + } +} + +void RelationSourceNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) +{ + fb_assert(stream <= MAX_STREAMS); + csb->csb_rpt[stream].csb_flags |= csb_active; + + pass2(tdbb, csb); +} + +RecordSource* RelationSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool /*innerSubStream*/) +{ + fb_assert(stream <= MAX_UCHAR); + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check + // ERR_post(Arg::Gds(isc_too_many_contexts)); + + opt->beds[++opt->beds[0]] = (UCHAR) stream; + + // we have found a base relation; record its stream + // number in the streams array as a candidate for + // merging into a river + + // TMN: Is the intention really to allow streams[0] to overflow? + // I must assume that is indeed not the intention (not to mention + // it would make code later on fail), so I added the following fb_assert. + fb_assert(opt->compileStreams[0] < MAX_STREAMS && opt->compileStreams[0] < MAX_UCHAR); + + opt->compileStreams[++opt->compileStreams[0]] = (UCHAR) stream; + + if (opt->rse->rse_jointype == blr_left) + opt->outerStreams.add(stream); + + // if we have seen any booleans or sort fields, we may be able to + // use an index to optimize them; retrieve the current format of + // all indices at this time so we can determine if it's possible + // AB: if a parentStack was available and conjunctCount was 0 + // then no indices where retrieved. Added also OR check on + // parentStack below. SF BUG # [ 508594 ] + + if (opt->conjunctCount || opt->rse->rse_sorted || opt->rse->rse_aggregate || opt->parentStack) + { + if (relation && !relation->rel_file && !relation->isVirtual()) + { + opt->opt_csb->csb_rpt[stream].csb_indices = + BTR_all(tdbb, relation, &opt->opt_csb->csb_rpt[stream].csb_idx, relation->getPages(tdbb)); + sortIndicesBySelectivity(&opt->opt_csb->csb_rpt[stream]); + markIndices(&opt->opt_csb->csb_rpt[stream], relation->rel_id); + } + else + opt->opt_csb->csb_rpt[stream].csb_indices = 0; + + const Format* format = CMP_format(tdbb, opt->opt_csb, stream); + opt->opt_csb->csb_rpt[stream].csb_cardinality = + OPT_getRelationCardinality(tdbb, relation, format); + } + + return NULL; +} + + +//-------------------- + + +// Parse an procedural view reference. +ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch* csb, + SSHORT blrOp) +{ + SET_TDBB(tdbb); + + jrd_prc* procedure = NULL; + string* aliasString = NULL; + QualifiedName name; + + switch (blrOp) + { + case blr_pid: + case blr_pid2: + { + const SSHORT pid = csb->csb_blr_reader.getWord(); + + if (blrOp == blr_pid2) + { + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); + } + + if (!(procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0))) + name.identifier.printf("id %d", pid); + + break; + } + + case blr_procedure: + case blr_procedure2: + case blr_procedure3: + case blr_procedure4: + { + if (blrOp == blr_procedure3 || blrOp == blr_procedure4) + PAR_name(csb, name.package); + + PAR_name(csb, name.identifier); + + if (blrOp == blr_procedure2 || blrOp == blr_procedure4) + { + aliasString = FB_NEW(csb->csb_pool) string(csb->csb_pool); + PAR_name(csb, *aliasString); + } + + procedure = MET_lookup_procedure(tdbb, name, false); + + break; + } + + default: + fb_assert(false); + } + + if (!procedure) + PAR_error(csb, Arg::Gds(isc_prcnotdef) << Arg::Str(name.toString())); + + if (procedure->prc_type == prc_executable) + { + const string name = procedure->getName().toString(); + + if (tdbb->getAttachment()->att_flags & ATT_gbak_attachment) + PAR_warning(Arg::Warning(isc_illegal_prc_type) << Arg::Str(name)); + else + PAR_error(csb, Arg::Gds(isc_illegal_prc_type) << Arg::Str(name)); + } + + ProcedureSourceNode* node = FB_NEW(*tdbb->getDefaultPool()) ProcedureSourceNode( + *tdbb->getDefaultPool()); + + node->procedure = procedure->getId(); + node->stream = PAR_context(csb, &node->context); + + csb->csb_rpt[node->stream].csb_procedure = procedure; + csb->csb_rpt[node->stream].csb_alias = aliasString; + + PAR_procedure_parms(tdbb, csb, procedure, node->in_msg.getAddress(), + node->inputs.getAddress(), true); + + if (csb->csb_g_flags & csb_get_dependencies) + PAR_dependency(tdbb, csb, node->stream, (SSHORT) -1, ""); + + return node; +} + +ProcedureSourceNode* ProcedureSourceNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + if (!copier.remap) + BUGCHECK(221); // msg 221 (CMP) copy: cannot remap + + ProcedureSourceNode* newSource = FB_NEW(*tdbb->getDefaultPool()) ProcedureSourceNode( + *tdbb->getDefaultPool()); + + // dimitr: See the appropriate code and comment in NodeCopier (in nod_argument). + // We must copy the message first and only then use the new pointer to + // copy the inputs properly. + newSource->in_msg = copier.copy(tdbb, in_msg); + + { // scope + AutoSetRestore<jrd_nod*> autoMessage(&copier.message, newSource->in_msg); + newSource->inputs = copier.copy(tdbb, inputs); + } + + newSource->stream = copier.csb->nextStream(); + copier.remap[stream] = (UCHAR) newSource->stream; + newSource->context = context; + newSource->procedure = procedure; + newSource->view = view; + CompilerScratch::csb_repeat* element = CMP_csb_element(copier.csb, newSource->stream); + // SKIDDER: Maybe we need to check if we really found a procedure? + element->csb_procedure = MET_lookup_procedure_id(tdbb, newSource->procedure, false, false, 0); + element->csb_view = newSource->view; + element->csb_view_stream = copier.remap[0]; + + copier.csb->csb_rpt[newSource->stream].csb_flags |= copier.csb->csb_rpt[stream].csb_flags & csb_no_dbkey; + + return newSource; +} + +void ProcedureSourceNode::pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* /*view*/) +{ + inputs = CMP_pass1(tdbb, csb, inputs); + in_msg = CMP_pass1(tdbb, csb, in_msg); +} + +void ProcedureSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/, + BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack) +{ + stack.push(this); // Assume that the source will be used. Push it on the final stream stack. + + pass1(tdbb, csb, csb->csb_view); + + jrd_prc* const proc = MET_lookup_procedure_id(tdbb, procedure, false, false, 0); + CMP_post_procedure_access(tdbb, csb, proc); + CMP_post_resource(&csb->csb_resources, proc, Resource::rsc_procedure, proc->getId()); + + jrd_rel* const parentView = csb->csb_view; + const USHORT viewStream = csb->csb_view_stream; + view = parentView; + + CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream); + element->csb_view = parentView; + fb_assert(viewStream <= MAX_STREAMS); + element->csb_view_stream = (UCHAR) viewStream; + + // in the case where there is a parent view, find the context name + + if (parentView) + { + const ViewContexts& ctx = parentView->rel_view_contexts; + const USHORT key = context; + size_t pos; + + if (ctx.find(key, pos)) + { + element->csb_alias = FB_NEW(csb->csb_pool) string( + csb->csb_pool, ctx[pos]->vcx_context_name); + } + } +} + +void ProcedureSourceNode::pass2(thread_db* tdbb, CompilerScratch* csb) +{ + CMP_pass2(tdbb, csb, inputs, NULL); + CMP_pass2(tdbb, csb, in_msg, NULL); +} + +void ProcedureSourceNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) +{ + fb_assert(stream <= MAX_STREAMS); + csb->csb_rpt[stream].csb_flags |= csb_active; + + pass2(tdbb, csb); +} + +RecordSource* ProcedureSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool /*innerSubStream*/) +{ + fb_assert(stream <= MAX_UCHAR); + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check + // ERR_post(Arg::Gds(isc_too_many_contexts)); + + opt->beds[++opt->beds[0]] = (UCHAR) stream; + + RecordSource* rsb = generate(tdbb, opt); + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = stream; + + return rsb; +} + +// Compile and optimize a record selection expression into a set of record source blocks (rsb's). +ProcedureScan* ProcedureSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt) +{ + SET_TDBB(tdbb); + + jrd_prc* const proc = MET_lookup_procedure_id(tdbb, procedure, false, false, 0); + + CompilerScratch* const csb = opt->opt_csb; + CompilerScratch::csb_repeat* const csbTail = &csb->csb_rpt[stream]; + const string alias = OPT_make_alias(tdbb, csb, csbTail); + + return FB_NEW(*tdbb->getDefaultPool()) ProcedureScan(csb, alias, stream, proc, inputs, in_msg); +} + +bool ProcedureSourceNode::computable(CompilerScratch* csb, SSHORT stream, bool idx_use, + bool allowOnlyCurrentStream, jrd_nod* /*value*/) +{ + if (inputs) + { + fb_assert(inputs->nod_type == nod_asn_list); + jrd_nod* const* ptr = inputs->nod_arg; + + for (const jrd_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++) + { + if (!OPT_computable(csb, *ptr, stream, idx_use, allowOnlyCurrentStream)) + return false; + } + } + + return true; +} + +void ProcedureSourceNode::findDependentFromStreams(const OptimizerRetrieval* optRet, + SortedStreamList* streamList) +{ + if (inputs) + { + fb_assert(inputs->nod_type == nod_asn_list); + jrd_nod* const* ptr = inputs->nod_arg; + + for (const jrd_nod* const* const end = ptr + inputs->nod_count; ptr < end; ptr++) + optRet->findDependentFromStreams(*ptr, streamList); + } +} + + +//-------------------- + + +// Parse an aggregate reference. +AggregateSourceNode* AggregateSourceNode::parse(thread_db* tdbb, CompilerScratch* csb) +{ + SET_TDBB(tdbb); + + AggregateSourceNode* node = FB_NEW(*tdbb->getDefaultPool()) AggregateSourceNode( + *tdbb->getDefaultPool()); + + node->stream = PAR_context(csb, NULL); + fb_assert(node->stream <= MAX_STREAMS); + node->rse = RseNode::getFrom(PAR_parse_node(tdbb, csb, TYPE_RSE)); + node->group = PAR_sort(tdbb, csb, blr_group_by, true); + node->map = parseMap(tdbb, csb, node->stream); + + return node; +} + +AggregateSourceNode* AggregateSourceNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + if (!copier.remap) + BUGCHECK(221); // msg 221 (CMP) copy: cannot remap + + AggregateSourceNode* newSource = FB_NEW(*tdbb->getDefaultPool()) AggregateSourceNode( + *tdbb->getDefaultPool()); + + fb_assert(stream <= MAX_STREAMS); + newSource->stream = copier.csb->nextStream(); + // fb_assert(newSource->stream <= MAX_UCHAR); + copier.remap[stream] = (UCHAR) newSource->stream; + CMP_csb_element(copier.csb, newSource->stream); + + copier.csb->csb_rpt[newSource->stream].csb_flags |= + copier.csb->csb_rpt[stream].csb_flags & csb_no_dbkey; + + newSource->rse = rse->copy(tdbb, copier); + if (group) + newSource->group = group->copy(tdbb, copier); + newSource->map = map->copy(tdbb, copier); + + return newSource; +} + +void AggregateSourceNode::ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const +{ + rse->ignoreDbKey(tdbb, csb, view); +} + +void AggregateSourceNode::pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view) +{ + fb_assert(stream <= MAX_STREAMS); + csb->csb_rpt[stream].csb_flags |= csb_no_dbkey; + rse->ignoreDbKey(tdbb, csb, view); + rse->pass1(tdbb, csb, csb->csb_view); + map->pass1(tdbb, csb); + if (group) + group->pass1(tdbb, csb); +} + +void AggregateSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/, + BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack) +{ + stack.push(this); // Assume that the source will be used. Push it on the final stream stack. + + fb_assert(stream <= MAX_STREAMS); + pass1(tdbb, csb, csb->csb_view); +} + +void AggregateSourceNode::pass2(thread_db* tdbb, CompilerScratch* csb) +{ + rse->pass2Rse(tdbb, csb); + map->pass2(tdbb, csb); + if (group) + group->pass2(tdbb, csb); + + fb_assert(stream <= MAX_STREAMS); + + processMap(tdbb, csb, map, &csb->csb_rpt[stream].csb_internal_format); + csb->csb_rpt[stream].csb_format = csb->csb_rpt[stream].csb_internal_format; +} + +void AggregateSourceNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) +{ + fb_assert(stream <= MAX_STREAMS); + csb->csb_rpt[stream].csb_flags |= csb_active; + + pass2(tdbb, csb); +} + +bool AggregateSourceNode::containsStream(USHORT checkStream) const +{ + // for aggregates, check current RseNode, if not found then check + // the sub-rse + + if (checkStream == stream) + return true; // do not mark as variant + + if (rse->containsStream(checkStream)) + return true; // do not mark as variant + + return false; +} + +RecordSource* AggregateSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool /*innerSubStream*/) +{ + fb_assert(stream <= MAX_UCHAR); + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check + // ERR_post(Arg::Gds(isc_too_many_contexts)); + + opt->beds[++opt->beds[0]] = (UCHAR) stream; + + BoolExprNodeStack::const_iterator stackEnd; + if (opt->parentStack) + stackEnd = opt->conjunctStack.merge(*opt->parentStack); + + RecordSource* rsb = generate(tdbb, opt, &opt->conjunctStack, stream); + + if (opt->parentStack) + opt->conjunctStack.split(stackEnd, *opt->parentStack); + + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = stream; + + return rsb; +} + +// Generate a RecordSource (Record Source Block) for each aggregate operation. +// Generate an AggregateSort (Aggregate SortedStream Block) for each DISTINCT aggregate. +RecordSource* AggregateSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt, + BoolExprNodeStack* parentStack, UCHAR shellStream) +{ + SET_TDBB(tdbb); + + CompilerScratch* const csb = opt->opt_csb; + rse->rse_sorted = group; + + // AB: Try to distribute items from the HAVING CLAUSE to the WHERE CLAUSE. + // Zip thru stack of booleans looking for fields that belong to shellStream. + // Those fields are mappings. Mappings that hold a plain field may be used + // to distribute. Handle the simple cases only. + BoolExprNodeStack deliverStack; + genDeliverUnmapped(tdbb, &deliverStack, map, parentStack, shellStream); + + // try to optimize MAX and MIN to use an index; for now, optimize + // only the simplest case, although it is probably possible + // to use an index in more complex situations + NestConst<jrd_nod>* ptr; + AggNode* aggNode = NULL; + + if (map->items.getCount() == 1 && (ptr = map->items.begin()) && + (aggNode = ExprNode::as<AggNode>((*ptr)->nod_arg[e_asgn_from])) && + (aggNode->aggInfo.blr == blr_agg_min || aggNode->aggInfo.blr == blr_agg_max)) + { + // generate a sort block which the optimizer will try to map to an index + + SortNode* aggregate = rse->rse_aggregate = + FB_NEW(*tdbb->getDefaultPool()) SortNode(*tdbb->getDefaultPool()); + + aggregate->expressions.add(aggNode->arg); + // in the max case, flag the sort as descending + aggregate->descending.add(aggNode->aggInfo.blr == blr_agg_max); + // 10-Aug-2004. Nickolay Samofatov - Unneeded nulls seem to be skipped somehow. + aggregate->nullOrder.add(rse_nulls_default); + } + + RecordSource* const nextRsb = OPT_compile(tdbb, csb, rse, &deliverStack); + + fb_assert(stream <= MAX_STREAMS); + fb_assert(stream <= MAX_UCHAR); + + // allocate and optimize the record source block + + AggregatedStream* const rsb = FB_NEW(*tdbb->getDefaultPool()) AggregatedStream(csb, stream, + (group ? &group->expressions : NULL), map, nextRsb); + + if (rse->rse_aggregate) + { + // The rse_aggregate is still set. That means the optimizer + // was able to match the field to an index, so flag that fact + // so that it can be handled in EVL_group + aggNode->indexed = true; + } + + OPT_gen_aggregate_distincts(tdbb, csb, map); + + return rsb; +} + +bool AggregateSourceNode::computable(CompilerScratch* csb, SSHORT stream, bool idx_use, + bool allowOnlyCurrentStream, jrd_nod* /*value*/) +{ + rse->rse_sorted = group; + return rse->computable(csb, stream, idx_use, allowOnlyCurrentStream, NULL); +} + +void AggregateSourceNode::findDependentFromStreams(const OptimizerRetrieval* optRet, + SortedStreamList* streamList) +{ + rse->rse_sorted = group; + rse->findDependentFromStreams(optRet, streamList); +} + + +//-------------------- + + +// Parse a union reference. +UnionSourceNode* UnionSourceNode::parse(thread_db* tdbb, CompilerScratch* csb, SSHORT blrOp) +{ + SET_TDBB(tdbb); + + // Make the node, parse the context number, get a stream assigned, + // and get the number of sub-RseNode's. + + UnionSourceNode* node = FB_NEW(*tdbb->getDefaultPool()) UnionSourceNode( + *tdbb->getDefaultPool()); + + node->recursive = blrOp == blr_recurse; + + node->stream = PAR_context(csb, NULL); + fb_assert(node->stream <= MAX_STREAMS); + + // assign separate context for mapped record if union is recursive + USHORT stream2 = node->stream; + + if (node->recursive) + { + stream2 = PAR_context(csb, 0); + node->mapStream = stream2; + } + + int count = (unsigned int) csb->csb_blr_reader.getByte(); + + // Pick up the sub-RseNode's and maps. + + while (--count >= 0) + { + node->clauses.push(RseNode::getFrom(PAR_parse_node(tdbb, csb, TYPE_RSE))); + node->maps.push(parseMap(tdbb, csb, stream2)); + } + + return node; +} + +UnionSourceNode* UnionSourceNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + if (!copier.remap) + BUGCHECK(221); // msg 221 (CMP) copy: cannot remap + + UnionSourceNode* newSource = FB_NEW(*tdbb->getDefaultPool()) UnionSourceNode( + *tdbb->getDefaultPool()); + newSource->recursive = recursive; + + fb_assert(stream <= MAX_STREAMS); + newSource->stream = copier.csb->nextStream(); + copier.remap[stream] = (UCHAR) newSource->stream; + CMP_csb_element(copier.csb, newSource->stream); + + USHORT oldStream = stream; + USHORT newStream = newSource->stream; + + if (newSource->recursive) + { + oldStream = mapStream; + fb_assert(oldStream <= MAX_STREAMS); + newStream = copier.csb->nextStream(); + newSource->mapStream = newStream; + copier.remap[oldStream] = (UCHAR) newStream; + CMP_csb_element(copier.csb, newStream); + } + + copier.csb->csb_rpt[newStream].csb_flags |= + copier.csb->csb_rpt[oldStream].csb_flags & csb_no_dbkey; + + NestConst<RseNode>* ptr = clauses.begin(); + NestConst<MapNode>* ptr2 = maps.begin(); + + for (NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr, ++ptr2) + { + newSource->clauses.add((*ptr)->copy(tdbb, copier)); + newSource->maps.add((*ptr2)->copy(tdbb, copier)); + } + + return newSource; +} + +void UnionSourceNode::ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const +{ + const NestConst<RseNode>* ptr = clauses.begin(); + + for (const NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr) + (*ptr)->ignoreDbKey(tdbb, csb, view); +} + +void UnionSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/, + BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack) +{ + stack.push(this); // Assume that the source will be used. Push it on the final stream stack. + + NestConst<RseNode>* ptr = clauses.begin(); + NestConst<MapNode>* ptr2 = maps.begin(); + + for (NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr, ++ptr2) + { + (*ptr)->pass1(tdbb, csb, csb->csb_view); + (*ptr2)->pass1(tdbb, csb); + } +} + +// Process a union clause of a RseNode. +void UnionSourceNode::pass2(thread_db* tdbb, CompilerScratch* csb) +{ + SET_TDBB(tdbb); + + // make up a format block sufficiently large to hold instantiated record + + const USHORT id = getStream(); + Format** format = &csb->csb_rpt[id].csb_internal_format; + + // Process RseNodes and map blocks. + + NestConst<RseNode>* ptr = clauses.begin(); + NestConst<MapNode>* ptr2 = maps.begin(); + + for (NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr, ++ptr2) + { + (*ptr)->pass2Rse(tdbb, csb); + (*ptr2)->pass2(tdbb, csb); + processMap(tdbb, csb, *ptr2, format); + csb->csb_rpt[id].csb_format = *format; + } + + if (recursive) + csb->csb_rpt[mapStream].csb_format = *format; +} + +void UnionSourceNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) +{ + fb_assert(stream <= MAX_STREAMS); + csb->csb_rpt[stream].csb_flags |= csb_active; + + pass2(tdbb, csb); +} + +bool UnionSourceNode::containsStream(USHORT checkStream) const +{ + // for unions, check current RseNode, if not found then check + // all sub-rse's + + if (checkStream == stream) + return true; // do not mark as variant + + const NestConst<RseNode>* ptr = clauses.begin(); + + for (const NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr) + { + if ((*ptr)->containsStream(checkStream)) + return true; + } + + return false; +} + +RecordSource* UnionSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool /*innerSubStream*/) +{ + const SSHORT i = (SSHORT) opt->keyStreams[0]; + computeDbKeyStreams(opt->keyStreams); + + BoolExprNodeStack::const_iterator stackEnd; + if (opt->parentStack) + stackEnd = opt->conjunctStack.merge(*opt->parentStack); + + RecordSource* rsb = generate(tdbb, opt, opt->keyStreams + i + 1, + (USHORT) (opt->keyStreams[0] - i), &opt->conjunctStack, stream); + + if (opt->parentStack) + opt->conjunctStack.split(stackEnd, *opt->parentStack); + + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = stream; + + return rsb; +} + +// Generate an union complex. +RecordSource* UnionSourceNode::generate(thread_db* tdbb, OptimizerBlk* opt, UCHAR* streams, + USHORT nstreams, BoolExprNodeStack* parentStack, UCHAR shellStream) +{ + SET_TDBB(tdbb); + + CompilerScratch* csb = opt->opt_csb; + HalfStaticArray<RecordSource*, OPT_STATIC_ITEMS> rsbs; + + const SLONG baseImpure = CMP_impure(csb, 0); + + NestConst<RseNode>* ptr = clauses.begin(); + NestConst<MapNode>* ptr2 = maps.begin(); + + for (NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr, ++ptr2) + { + RseNode* rse = *ptr; + MapNode* map = *ptr2; + + // AB: Try to distribute booleans from the top rse for an UNION to + // the WHERE clause of every single rse. + // hvlad: don't do it for recursive unions else they will work wrong ! + BoolExprNodeStack deliverStack; + if (!recursive) + genDeliverUnmapped(tdbb, &deliverStack, map, parentStack, shellStream); + + rsbs.add(OPT_compile(tdbb, csb, rse, &deliverStack)); + + // hvlad: activate recursive union itself after processing first (non-recursive) + // member to allow recursive members be optimized + if (recursive) + csb->csb_rpt[stream].csb_flags |= csb_active; + } + + if (recursive) + { + fb_assert(rsbs.getCount() == 2 && maps.getCount() == 2); + // hvlad: save size of inner impure area and context of mapped record + // for recursive processing later + return FB_NEW(*tdbb->getDefaultPool()) RecursiveStream(csb, stream, mapStream, + rsbs[0], rsbs[1], maps[0], maps[1], nstreams, streams, baseImpure); + } + + return FB_NEW(*tdbb->getDefaultPool()) Union(csb, stream, clauses.getCount(), rsbs.begin(), + maps.begin(), nstreams, streams); +} + +// Identify all of the streams for which a dbkey may need to be carried through a sort. +void UnionSourceNode::computeDbKeyStreams(UCHAR* streams) const +{ + const NestConst<RseNode>* ptr = clauses.begin(); + + for (const NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr) + (*ptr)->computeDbKeyStreams(streams); +} + +bool UnionSourceNode::computable(CompilerScratch* csb, SSHORT stream, bool idx_use, + bool allowOnlyCurrentStream, jrd_nod* /*value*/) +{ + NestConst<RseNode>* ptr = clauses.begin(); + + for (NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr) + { + if (!(*ptr)->computable(csb, stream, idx_use, allowOnlyCurrentStream, NULL)) + return false; + } + + return true; +} + +void UnionSourceNode::findDependentFromStreams(const OptimizerRetrieval* optRet, + SortedStreamList* streamList) +{ + NestConst<RseNode>* ptr = clauses.begin(); + + for (NestConst<RseNode>* const end = clauses.end(); ptr != end; ++ptr) + (*ptr)->findDependentFromStreams(optRet, streamList); +} + + +//-------------------- + + +// Parse a window reference. +WindowSourceNode* WindowSourceNode::parse(thread_db* tdbb, CompilerScratch* csb) +{ + SET_TDBB(tdbb); + + WindowSourceNode* node = FB_NEW(*tdbb->getDefaultPool()) WindowSourceNode( + *tdbb->getDefaultPool()); + + node->rse = RseNode::getFrom(PAR_parse_node(tdbb, csb, TYPE_RSE)); + + unsigned partitionCount = csb->csb_blr_reader.getByte(); + + for (unsigned i = 0; i < partitionCount; ++i) + node->parsePartitionBy(tdbb, csb); + + return node; +} + +// Parse PARTITION BY subclauses of window functions. +void WindowSourceNode::parsePartitionBy(thread_db* tdbb, CompilerScratch* csb) +{ + SET_TDBB(tdbb); + + if (csb->csb_blr_reader.getByte() != blr_partition_by) + PAR_syntax_error(csb, "blr_partition_by"); + + SSHORT context; + Partition& partition = partitions.add(); + partition.stream = PAR_context(csb, &context); + + const UCHAR count = csb->csb_blr_reader.getByte(); + + if (count != 0) + { + partition.group = PAR_sort_internal(tdbb, csb, blr_partition_by, count); + partition.regroup = PAR_sort_internal(tdbb, csb, blr_partition_by, count); + } + + partition.order = PAR_sort(tdbb, csb, blr_sort, true); + partition.map = parseMap(tdbb, csb, partition.stream); +} + +WindowSourceNode* WindowSourceNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + if (!copier.remap) + BUGCHECK(221); // msg 221 (CMP) copy: cannot remap + + WindowSourceNode* newSource = FB_NEW(*tdbb->getDefaultPool()) WindowSourceNode( + *tdbb->getDefaultPool()); + + newSource->rse = rse->copy(tdbb, copier); + + for (ObjectsArray<Partition>::iterator inputPartition = partitions.begin(); + inputPartition != partitions.end(); + ++inputPartition) + { + fb_assert(inputPartition->stream <= MAX_STREAMS); + + Partition& copyPartition = newSource->partitions.add(); + + copyPartition.stream = copier.csb->nextStream(); + // fb_assert(copyPartition.stream <= MAX_UCHAR); + + copier.remap[inputPartition->stream] = (UCHAR) copyPartition.stream; + CMP_csb_element(copier.csb, copyPartition.stream); + + if (inputPartition->group) + copyPartition.group = inputPartition->group->copy(tdbb, copier); + if (inputPartition->regroup) + copyPartition.regroup = inputPartition->regroup->copy(tdbb, copier); + if (inputPartition->order) + copyPartition.order = inputPartition->order->copy(tdbb, copier); + copyPartition.map = inputPartition->map->copy(tdbb, copier); + } + + return newSource; +} + +void WindowSourceNode::ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const +{ + rse->ignoreDbKey(tdbb, csb, view); +} + +void WindowSourceNode::pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* view) +{ + for (ObjectsArray<Partition>::iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + fb_assert(partition->stream <= MAX_STREAMS); + csb->csb_rpt[partition->stream].csb_flags |= csb_no_dbkey; + } + + rse->ignoreDbKey(tdbb, csb, view); + rse->pass1(tdbb, csb, csb->csb_view); + + for (ObjectsArray<Partition>::iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + if (partition->group) + partition->group->pass1(tdbb, csb); + if (partition->regroup) + partition->regroup->pass1(tdbb, csb); + if (partition->order) + partition->order->pass1(tdbb, csb); + partition->map->pass1(tdbb, csb); + } +} + +void WindowSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/, + BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack) +{ + stack.push(this); // Assume that the source will be used. Push it on the final stream stack. + + pass1(tdbb, csb, csb->csb_view); +} + +void WindowSourceNode::pass2(thread_db* tdbb, CompilerScratch* csb) +{ + rse->pass2Rse(tdbb, csb); + + for (ObjectsArray<Partition>::iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + partition->map->pass2(tdbb, csb); + if (partition->group) + partition->group->pass2(tdbb, csb); + if (partition->order) + partition->order->pass2(tdbb, csb); + + fb_assert(partition->stream <= MAX_STREAMS); + + processMap(tdbb, csb, partition->map, &csb->csb_rpt[partition->stream].csb_internal_format); + csb->csb_rpt[partition->stream].csb_format = + csb->csb_rpt[partition->stream].csb_internal_format; + } + + for (ObjectsArray<Partition>::iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + if (partition->regroup) + partition->regroup->pass2(tdbb, csb); + } +} + +void WindowSourceNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) +{ + pass2(tdbb, csb); + + for (ObjectsArray<Partition>::iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + csb->csb_rpt[partition->stream].csb_flags |= csb_active; + } +} + +bool WindowSourceNode::containsStream(USHORT checkStream) const +{ + for (ObjectsArray<Partition>::const_iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + if (checkStream == partition->stream) + return true; // do not mark as variant + } + + if (rse->containsStream(checkStream)) + return true; // do not mark as variant + + return false; +} + +RecordSource* WindowSourceNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool /*innerSubStream*/) +{ + for (ObjectsArray<Partition>::iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + fb_assert(partition->stream <= MAX_UCHAR); + fb_assert(opt->beds[0] < MAX_STREAMS && opt->beds[0] < MAX_UCHAR); // debug check + //if (opt->beds[0] >= MAX_STREAMS) // all builds check + // ERR_post(Arg::Gds(isc_too_many_contexts)); + + opt->beds[++opt->beds[0]] = (UCHAR) partition->stream; + } + + BoolExprNodeStack deliverStack; + + RecordSource* rsb = FB_NEW(*tdbb->getDefaultPool()) WindowedStream(opt->opt_csb, partitions, + OPT_compile(tdbb, opt->opt_csb, rse, &deliverStack)); + + StreamsArray rsbStreams; + rsb->findUsedStreams(rsbStreams); + + for (StreamsArray::iterator i = rsbStreams.begin(); i != rsbStreams.end(); ++i) + { + fb_assert(opt->localStreams[0] < MAX_STREAMS && opt->localStreams[0] < MAX_UCHAR); + opt->localStreams[++opt->localStreams[0]] = *i; + } + + return rsb; +} + +bool WindowSourceNode::computable(CompilerScratch* csb, SSHORT stream, bool idx_use, + bool allowOnlyCurrentStream, jrd_nod* /*value*/) +{ + return rse->computable(csb, stream, idx_use, allowOnlyCurrentStream, NULL); +} + +void WindowSourceNode::getStreams(StreamsArray& list) const +{ + for (ObjectsArray<Partition>::const_iterator partition = partitions.begin(); + partition != partitions.end(); + ++partition) + { + list.add(partition->stream); + } +} + +void WindowSourceNode::findDependentFromStreams(const OptimizerRetrieval* optRet, + SortedStreamList* streamList) +{ + rse->findDependentFromStreams(optRet, streamList); +} + + +//-------------------- + + +RseNode* RseNode::copy(thread_db* tdbb, NodeCopier& copier) +{ + RseNode* newSource = FB_NEW(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool()); + + NestConst<RecordSourceNode>* ptr = rse_relations.begin(); + + for (NestConst<RecordSourceNode>* const end = rse_relations.end(); ptr != end; ++ptr) + newSource->rse_relations.add((*ptr)->copy(tdbb, copier)); + + newSource->flags = flags; + newSource->rse_jointype = rse_jointype; + newSource->rse_first = copier.copy(tdbb, rse_first); + newSource->rse_skip = copier.copy(tdbb, rse_skip); + + if (rse_boolean) + newSource->rse_boolean = rse_boolean->copy(tdbb, copier); + + if (rse_sorted) + newSource->rse_sorted = rse_sorted->copy(tdbb, copier); + + if (rse_projection) + newSource->rse_projection = rse_projection->copy(tdbb, copier); + + return newSource; +} + +// For each relation or aggregate in the RseNode, mark it as not having a dbkey. +void RseNode::ignoreDbKey(thread_db* tdbb, CompilerScratch* csb, const jrd_rel* view) const +{ + const NestConst<RecordSourceNode>* ptr = rse_relations.begin(); + + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); ptr != end; ++ptr) + (*ptr)->ignoreDbKey(tdbb, csb, view); +} + +// Process a record select expression during pass 1 of compilation. +// Mostly this involves expanding views. +void RseNode::pass1(thread_db* tdbb, CompilerScratch* csb, jrd_rel* /*view*/) +{ + SET_TDBB(tdbb); + + // for scoping purposes, maintain a stack of RseNode's which are + // currently being parsed; if there are none on the stack as + // yet, mark the RseNode as variant to make sure that statement- + // level aggregates are not treated as invariants -- bug #6535 + + bool topLevelRse = true; + + for (LegacyNodeOrRseNode* node = csb->csb_current_nodes.begin(); + node != csb->csb_current_nodes.end(); ++node) + { + if (node->rseNode) + { + topLevelRse = false; + break; + } + } + + if (topLevelRse) + flags |= FLAG_VARIANT; + + csb->csb_current_nodes.push(this); + + RecordSourceNodeStack stack; + BoolExprNode* boolean = NULL; + SortNode* sort = rse_sorted; + SortNode* project = rse_projection; + jrd_nod* first = rse_first; + jrd_nod* skip = rse_skip; + PlanNode* plan = rse_plan; + + // zip thru RseNode expanding views and inner joins + NestConst<RecordSourceNode>* arg = rse_relations.begin(); + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); arg != end; ++arg) + processSource(tdbb, csb, this, *arg, &boolean, stack); + + // Now, rebuild the RseNode block. + + rse_relations.resize(stack.getCount()); + arg = rse_relations.end(); + + while (stack.hasData()) + *--arg = stack.pop(); + + AutoSetRestore<bool> autoValidateExpr(&csb->csb_validate_expr, false); + + // finish of by processing other clauses + + if (first) + rse_first = CMP_pass1(tdbb, csb, first); + + if (skip) + rse_skip = CMP_pass1(tdbb, csb, skip); + + if (boolean) + { + if (rse_boolean) + { + BinaryBoolNode* andNode = FB_NEW(csb->csb_pool) BinaryBoolNode(csb->csb_pool, blr_and); + andNode->arg1 = boolean; + andNode->arg2 = rse_boolean->pass1(tdbb, csb); + + rse_boolean = andNode; + } + else + rse_boolean = boolean; + } + else if (rse_boolean) + rse_boolean = rse_boolean->pass1(tdbb, csb); + + if (sort) + { + sort->pass1(tdbb, csb); + rse_sorted = sort; + } + + if (project) + { + project->pass1(tdbb, csb); + rse_projection = project; + } + + if (plan) + rse_plan = plan; + + // we are no longer in the scope of this RseNode + csb->csb_current_nodes.pop(); +} + +void RseNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, + BoolExprNode** boolean, RecordSourceNodeStack& stack) +{ + // in the case of an RseNode, it is possible that a new RseNode will be generated, + // so wait to process the source before we push it on the stack (bug 8039) + + // The addition of the JOIN syntax for specifying inner joins causes an + // RseNode tree to be generated, which is undesirable in the simplest case + // where we are just trying to inner join more than 2 streams. If possible, + // try to flatten the tree out before we go any further. + + if (!rse->rse_jointype && !rse_jointype && !rse_sorted && !rse_projection && + !rse_first && !rse_skip && !rse_plan) + { + NestConst<RecordSourceNode>* arg = rse_relations.begin(); + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); arg != end; ++arg) + processSource(tdbb, csb, rse, *arg, boolean, stack); + + // fold in the boolean for this inner join with the one for the parent + + if (rse_boolean) + { + BoolExprNode* node = rse_boolean->pass1(tdbb, csb); + + if (*boolean) + { + BinaryBoolNode* andNode = FB_NEW(csb->csb_pool) BinaryBoolNode( + csb->csb_pool, blr_and); + andNode->arg1 = node; + andNode->arg2 = *boolean; + + *boolean = andNode; + } + else + *boolean = node; + } + + return; + } + + pass1(tdbb, csb, csb->csb_view); + stack.push(this); +} + +// Perform the first half of record selection expression compilation. +// The actual optimization is done in "post_rse". +void RseNode::pass2Rse(thread_db* tdbb, CompilerScratch* csb) +{ + SET_TDBB(tdbb); + + // Maintain stack of RSEe for scoping purposes + csb->csb_current_nodes.push(this); + + if (rse_first) + CMP_pass2(tdbb, csb, rse_first, NULL); + + if (rse_skip) + CMP_pass2(tdbb, csb, rse_skip, NULL); + + NestConst<RecordSourceNode>* ptr = rse_relations.begin(); + + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); ptr != end; ++ptr) + (*ptr)->pass2Rse(tdbb, csb); + + if (rse_boolean) + rse_boolean->pass2(tdbb, csb); + + if (rse_sorted) + rse_sorted->pass2(tdbb, csb); + + if (rse_projection) + rse_projection->pass2(tdbb, csb); + + // If the user has submitted a plan for this RseNode, check it for correctness. + + if (rse_plan) + { + planSet(csb, rse_plan); + planCheck(csb); + } + + csb->csb_current_nodes.pop(); +} + +// Return true if stream is contained in the specified RseNode. +bool RseNode::containsStream(USHORT checkStream) const +{ + // Look through all relation nodes in this RseNode to see + // if the field references this instance of the relation. + + const NestConst<RecordSourceNode>* ptr = rse_relations.begin(); + + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); ptr != end; ++ptr) + { + const RecordSourceNode* sub = *ptr; + + if (sub->containsStream(checkStream)) + return true; // do not mark as variant + } + + return false; +} + +RecordSource* RseNode::compile(thread_db* tdbb, OptimizerBlk* opt, bool innerSubStream) +{ + // for nodes which are not relations, generate an rsb to + // represent that work has to be done to retrieve them; + // find all the substreams involved and compile them as well + + computeRseStreams(opt->opt_csb, opt->beds); + computeRseStreams(opt->opt_csb, opt->localStreams); + computeDbKeyStreams(opt->keyStreams); + + RecordSource* rsb; + + // pass RseNode boolean only to inner substreams because join condition + // should never exclude records from outer substreams + if (opt->rse->rse_jointype == blr_inner || (opt->rse->rse_jointype == blr_left && innerSubStream)) + { + // AB: For an (X LEFT JOIN Y) mark the outer-streams (X) as + // active because the inner-streams (Y) are always "dependent" + // on the outer-streams. So that index retrieval nodes could be made. + // For an INNER JOIN mark previous generated RecordSource's as active. + if (opt->rse->rse_jointype == blr_left) + { + for (StreamsArray::iterator i = opt->outerStreams.begin(); i != opt->outerStreams.end(); ++i) + opt->opt_csb->csb_rpt[*i].csb_flags |= csb_active; + } + + //const BoolExprNodeStack::iterator stackSavepoint(opt->conjunctStack); + BoolExprNodeStack::const_iterator stackEnd; + BoolExprNodeStack deliverStack; + + if (opt->rse->rse_jointype != blr_inner) + { + // Make list of nodes that can be delivered to an outer-stream. + // In fact these are all nodes except when a IS NULL comparison is done. + // Note! Don't forget that this can be burried inside a expression + // such as "CASE WHEN (FieldX IS NULL) THEN 0 ELSE 1 END = 0" + BoolExprNodeStack::iterator stackItem; + if (opt->parentStack) + stackItem = *opt->parentStack; + + for (; stackItem.hasData(); ++stackItem) + { + BoolExprNode* deliverNode = stackItem.object(); + PossibleUnknownFinder finder; + + if (!deliverNode->jrdPossibleUnknownFinder(finder)) + deliverStack.push(deliverNode); + } + + stackEnd = opt->conjunctStack.merge(deliverStack); + } + else + { + if (opt->parentStack) + stackEnd = opt->conjunctStack.merge(*opt->parentStack); + } + + rsb = OPT_compile(tdbb, opt->opt_csb, this, &opt->conjunctStack); + + if (opt->rse->rse_jointype != blr_inner) + { + // Remove previously added parent conjuctions from the stack. + opt->conjunctStack.split(stackEnd, deliverStack); + } + else + { + if (opt->parentStack) + opt->conjunctStack.split(stackEnd, *opt->parentStack); + } + + if (opt->rse->rse_jointype == blr_left) + { + for (StreamsArray::iterator i = opt->outerStreams.begin(); i != opt->outerStreams.end(); ++i) + opt->opt_csb->csb_rpt[*i].csb_flags &= ~csb_active; + } + } + else + rsb = OPT_compile(tdbb, opt->opt_csb, this, opt->parentStack); + + return rsb; +} + +// Identify the streams that make up a RseNode. +void RseNode::computeRseStreams(const CompilerScratch* csb, UCHAR* streams) const +{ + const NestConst<RecordSourceNode>* ptr = rse_relations.begin(); + + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); ptr != end; ++ptr) + { + const RecordSourceNode* node = *ptr; + + if (node->type == RseNode::TYPE) + static_cast<const RseNode*>(node)->computeRseStreams(csb, streams); + else + { + StreamsArray sourceStreams; + node->getStreams(sourceStreams); + + for (StreamsArray::iterator i = sourceStreams.begin(); i != sourceStreams.end(); ++i) + { + fb_assert(streams[0] < MAX_STREAMS && streams[0] < MAX_UCHAR); + streams[++streams[0]] = (UCHAR) *i; + } + } + } +} + +// Check that all streams in the RseNode have a plan specified for them. +// If they are not, there are streams in the RseNode which were not mentioned in the plan. +void RseNode::planCheck(const CompilerScratch* csb) const +{ + // if any streams are not marked with a plan, give an error + + const NestConst<RecordSourceNode>* ptr = rse_relations.begin(); + for (const NestConst<RecordSourceNode>* const end = rse_relations.end(); ptr != end; ++ptr) + { + const RecordSourceNode* node = *ptr; + + if (node->type == RelationSourceNode::TYPE) + { + const USHORT stream = node->getStream(); + + if (!(csb->csb_rpt[stream].csb_plan)) + { + ERR_post(Arg::Gds(isc_no_stream_plan) << + Arg::Str(csb->csb_rpt[stream].csb_relation->rel_name)); + } + } + else if (node->type == RseNode::TYPE) + static_cast<const RseNode*>(node)->planCheck(csb); + } +} + +// Go through the streams in the plan, find the corresponding streams in the RseNode and store the +// plan for that stream. Do it once and only once to make sure there is a one-to-one correspondence +// between streams in the query and streams in the plan. +void RseNode::planSet(CompilerScratch* csb, PlanNode* plan) +{ + if (plan->type == PlanNode::TYPE_JOIN) + { + for (NestConst<PlanNode>* ptr = plan->subNodes.begin(), *end = plan->subNodes.end(); + ptr != end; + ++ptr) + { + planSet(csb, *ptr); + } + } + + if (plan->type != PlanNode::TYPE_RETRIEVE) + return; + + const jrd_rel* viewRelation = NULL; + const jrd_rel* planRelation = plan->relationNode->relation; + const char* planAlias = plan->relationNode->alias; + + // find the tail for the relation specified in the RseNode + + const USHORT stream = plan->relationNode->getStream(); + CompilerScratch::csb_repeat* tail = &csb->csb_rpt[stream]; + + // if the plan references a view, find the real base relation + // we are interested in by searching the view map + UCHAR* map = NULL; + + if (tail->csb_map) + { + const TEXT* p = planAlias; + + // if the user has specified an alias, skip past it to find the alias + // for the base table (if multiple aliases are specified) + if (p && *p && + ((tail->csb_relation && !strcmpSpace(tail->csb_relation->rel_name.c_str(), p)) || + (tail->csb_alias && !strcmpSpace(tail->csb_alias->c_str(), p)))) + { + while (*p && *p != ' ') + p++; + + if (*p == ' ') + p++; + } + + // loop through potentially a stack of views to find the appropriate base table + UCHAR* mapBase; + + while ( (mapBase = tail->csb_map) ) + { + map = mapBase; + tail = &csb->csb_rpt[*map]; + viewRelation = tail->csb_relation; + + // if the plan references the view itself, make sure that + // the view is on a single table; if it is, fix up the plan + // to point to the base relation + + if (viewRelation->rel_id == planRelation->rel_id) + { + if (!mapBase[2]) + { + map++; + tail = &csb->csb_rpt[*map]; + } + else + { + // view %s has more than one base relation; use aliases to distinguish + ERR_post(Arg::Gds(isc_view_alias) << Arg::Str(planRelation->rel_name)); + } + + break; + } + + viewRelation = NULL; + + // if the user didn't specify an alias (or didn't specify one + // for this level), check to make sure there is one and only one + // base relation in the table which matches the plan relation + + if (!*p) + { + const jrd_rel* duplicateRelation = NULL; + UCHAR* duplicateMap = mapBase; + + map = NULL; + + for (duplicateMap++; *duplicateMap; ++duplicateMap) + { + CompilerScratch::csb_repeat* duplicateTail = &csb->csb_rpt[*duplicateMap]; + const jrd_rel* relation = duplicateTail->csb_relation; + + if (relation && relation->rel_id == planRelation->rel_id) + { + if (duplicateRelation) + { + // table %s is referenced twice in view; use an alias to distinguish + ERR_post(Arg::Gds(isc_duplicate_base_table) << + Arg::Str(duplicateRelation->rel_name)); + } + else + { + duplicateRelation = relation; + map = duplicateMap; + tail = duplicateTail; + } + } + } + + break; + } + + // look through all the base relations for a match + + map = mapBase; + for (map++; *map; map++) + { + tail = &csb->csb_rpt[*map]; + const jrd_rel* relation = tail->csb_relation; + + // match the user-supplied alias with the alias supplied + // with the view definition; failing that, try the base + // table name itself + + // ... [truncated message content] |
From: <di...@us...> - 2010-10-14 05:27:15
|
Revision: 51684 http://firebird.svn.sourceforge.net/firebird/?rev=51684&view=rev Author: dimitr Date: 2010-10-14 05:27:08 +0000 (Thu, 14 Oct 2010) Log Message: ----------- Front ported my recent changes. I'm unable to verify the compilation now, sorry. Modified Paths: -------------- firebird/trunk/src/jrd/JrdStatement.cpp firebird/trunk/src/jrd/blb.cpp firebird/trunk/src/jrd/cmp_proto.h firebird/trunk/src/jrd/dfw.epp firebird/trunk/src/jrd/irq.h firebird/trunk/src/jrd/met.epp firebird/trunk/src/jrd/met_proto.h firebird/trunk/src/jrd/par.cpp firebird/trunk/src/jrd/scl.epp firebird/trunk/src/jrd/scl_proto.h firebird/trunk/src/jrd/vio.cpp Modified: firebird/trunk/src/jrd/JrdStatement.cpp =================================================================== --- firebird/trunk/src/jrd/JrdStatement.cpp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/JrdStatement.cpp 2010-10-14 05:27:08 UTC (rev 51684) @@ -573,9 +573,7 @@ continue; } if (access->acc_type == SCL_object_column && - (MET_lookup_field(tdbb, ownerRelation, access->acc_name, - &access->acc_security_name) >= 0 || - MET_relation_default_class(tdbb, ownerRelation->rel_name, access->acc_security_name))) + (ownerRelation->rel_name == access->acc_r_name)) { continue; } Modified: firebird/trunk/src/jrd/blb.cpp =================================================================== --- firebird/trunk/src/jrd/blb.cpp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/blb.cpp 2010-10-14 05:27:08 UTC (rev 51684) @@ -1661,7 +1661,7 @@ SSHORT n; if (info.sdl_info_field.length()) { - n = MET_lookup_field(tdbb, relation, info.sdl_info_field, 0); + n = MET_lookup_field(tdbb, relation, info.sdl_info_field); } else { n = info.sdl_info_fid; Modified: firebird/trunk/src/jrd/cmp_proto.h =================================================================== --- firebird/trunk/src/jrd/cmp_proto.h 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/cmp_proto.h 2010-10-14 05:27:08 UTC (rev 51684) @@ -51,17 +51,7 @@ void CMP_post_access(Jrd::thread_db*, Jrd::CompilerScratch*, const Firebird::MetaName&, SLONG, Jrd::SecurityClass::flags_t, SLONG type_name, const Firebird::MetaName&, - const Firebird::MetaName&); -inline void CMP_post_access(Jrd::thread_db* tdbb, - Jrd::CompilerScratch* csb, - const Firebird::MetaName& security_name, - SLONG view_id, - Jrd::SecurityClass::flags_t mask, - SLONG type_name, - const Firebird::MetaName& name) -{ - CMP_post_access(tdbb, csb, security_name, view_id, mask, type_name, name, ""); -} + const Firebird::MetaName& = ""); void CMP_post_procedure_access(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_prc*); void CMP_post_resource(Jrd::ResourceList*, void*, Jrd::Resource::rsc_s, USHORT); Modified: firebird/trunk/src/jrd/dfw.epp =================================================================== --- firebird/trunk/src/jrd/dfw.epp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/dfw.epp 2010-10-14 05:27:08 UTC (rev 51684) @@ -4315,7 +4315,7 @@ relation = MET_lookup_relation_id(tdbb, work->dfw_id, false); if (relation) { - const int id = MET_lookup_field(tdbb, relation, work->dfw_name, 0); + const int id = MET_lookup_field(tdbb, relation, work->dfw_name); if (id >= 0) { vec<jrd_fld*>* vector = relation->rel_fields; Modified: firebird/trunk/src/jrd/irq.h =================================================================== --- firebird/trunk/src/jrd/irq.h 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/irq.h 2010-10-14 05:27:08 UTC (rev 51684) @@ -106,7 +106,6 @@ irq_format6, // make a new format for a record irq_r_gen_id_num, // lookup generator by ID. irq_verify_role_name, // ensure role exists in roles & user_privileges. - irq_l_relation_defsec, // check the default sec class name against rel. irq_m_index_seg, // modify per-segment index selectivity irq_l_subtype, // lookup subtype (charset/collation) Modified: firebird/trunk/src/jrd/met.epp =================================================================== --- firebird/trunk/src/jrd/met.epp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/met.epp 2010-10-14 05:27:08 UTC (rev 51684) @@ -1926,8 +1926,7 @@ int MET_lookup_field(thread_db* tdbb, jrd_rel* relation, - const MetaName& name, - const MetaName* security_name) + const MetaName& name) { /************************************** * @@ -1937,9 +1936,6 @@ * * Functional description * Look up a field name. - * Additionally, if security_name is a not null pointer, - * it's used to include the condition that it should match - * the field's security class name, too. * * if the field is not found return -1 * @@ -1963,14 +1959,7 @@ jrd_fld* field = *fieldIter; if (field->fld_name == name) { - if (!security_name) - { - return id; - } - if (field->fld_security_name == *security_name) - { - return id; - } + return id; } } } @@ -1993,15 +1982,7 @@ X.RDB$FIELD_ID NOT MISSING AND X.RDB$FIELD_NAME EQ name.c_str() { - if (!security_name) - id = X.RDB$FIELD_ID; - else - { - if ((!X.RDB$SECURITY_CLASS.NULL) && (*security_name == X.RDB$SECURITY_CLASS)) - { - id = X.RDB$FIELD_ID; - } - } + id = X.RDB$FIELD_ID; } END_FOR @@ -3254,48 +3235,6 @@ } -bool MET_relation_default_class(thread_db* tdbb, const MetaName& relation_name, - const MetaName& default_security_class_name) -{ -/************************************** - * - * M E T _ r e l a t i o n _ d e f a u l t _ c l a s s - * - ************************************** - * - * Functional description - * Checks that a given security class is the default for - * a given relation, returning TRUE if there's a match. - * It can be made obsolete in the future if jrd_rel struct - * gets another field, although metadata loading order - * would not be safe when compared with this function. - * - **************************************/ - SET_TDBB (tdbb); - Jrd::Attachment* attachment = tdbb->getAttachment(); - Database* dbb = tdbb->getDatabase(); - CHECK_DBB (dbb); - - bool found = false; - AutoCacheRequest request (tdbb, irq_l_relation_defsec, IRQ_REQUESTS); - - FOR (REQUEST_HANDLE request) - REL IN RDB$RELATIONS WITH REL.RDB$RELATION_NAME EQ relation_name.c_str() - { - if (!REL.RDB$DEFAULT_CLASS.NULL) - { - if (default_security_class_name == REL.RDB$DEFAULT_CLASS) - { - found = true; - } - } - } - END_FOR - - return found; -} - - void MET_release_existence(thread_db* tdbb, jrd_rel* relation) { /************************************** Modified: firebird/trunk/src/jrd/met_proto.h =================================================================== --- firebird/trunk/src/jrd/met_proto.h 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/met_proto.h 2010-10-14 05:27:08 UTC (rev 51684) @@ -87,7 +87,7 @@ void MET_lookup_cnstrt_for_trigger(Jrd::thread_db*, Firebird::MetaName&, Firebird::MetaName&, const Firebird::MetaName&); void MET_lookup_exception(Jrd::thread_db*, SLONG, /* OUT */ Firebird::MetaName&, /* OUT */ Firebird::string*); SLONG MET_lookup_exception_number(Jrd::thread_db*, const Firebird::MetaName&); -int MET_lookup_field(Jrd::thread_db*, Jrd::jrd_rel*, const Firebird::MetaName&, const Firebird::MetaName*); +int MET_lookup_field(Jrd::thread_db*, Jrd::jrd_rel*, const Firebird::MetaName&); Jrd::BlobFilter* MET_lookup_filter(Jrd::thread_db*, SSHORT, SSHORT); SLONG MET_lookup_generator(Jrd::thread_db*, const TEXT*); void MET_lookup_generator_id(Jrd::thread_db*, SLONG, Firebird::MetaName&); @@ -105,7 +105,6 @@ void MET_prepare(Jrd::thread_db*, Jrd::jrd_tra*, USHORT, const UCHAR*); Jrd::jrd_prc* MET_procedure(Jrd::thread_db*, int, bool, USHORT); Jrd::jrd_rel* MET_relation(Jrd::thread_db*, USHORT); -bool MET_relation_default_class (Jrd::thread_db*, const Firebird::MetaName&, const Firebird::MetaName&); void MET_release_existence(Jrd::thread_db*, Jrd::jrd_rel*); void MET_release_trigger(Jrd::thread_db*, Jrd::trig_vec**, const Firebird::MetaName&); void MET_release_triggers(Jrd::thread_db*, Jrd::trig_vec**); Modified: firebird/trunk/src/jrd/par.cpp =================================================================== --- firebird/trunk/src/jrd/par.cpp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/par.cpp 2010-10-14 05:27:08 UTC (rev 51684) @@ -624,7 +624,7 @@ jrd_prc* procedure = csb->csb_rpt[stream].csb_procedure; const SSHORT id = procedure ? find_proc_field(procedure, base_field) : - MET_lookup_field (tdbb, csb->csb_rpt[stream].csb_relation, base_field, 0); + MET_lookup_field(tdbb, csb->csb_rpt[stream].csb_relation, base_field); if (id < 0) return NULL; @@ -1352,7 +1352,7 @@ } PAR_name(csb, name); - if ((id = MET_lookup_field(tdbb, relation, name.c_str(), 0)) < 0) + if ((id = MET_lookup_field(tdbb, relation, name)) < 0) { if (csb->csb_g_flags & csb_validation) { Modified: firebird/trunk/src/jrd/scl.epp =================================================================== --- firebird/trunk/src/jrd/scl.epp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/scl.epp 2010-10-14 05:27:08 UTC (rev 51684) @@ -162,7 +162,8 @@ const Firebird::MetaName& obj_name, SecurityClass::flags_t mask, SLONG type, - const char* name) + const Firebird::MetaName& name, + const Firebird::MetaName& r_name) { /************************************** * @@ -245,50 +246,15 @@ { fb_assert(type != SCL_object_database); const char* typeAsStr = accTypeNumToStr(type); + const Firebird::string fullName = r_name.hasData() ? + r_name.c_str() + Firebird::string(".") + name.c_str() : name.c_str(); ERR_post(Arg::Gds(isc_no_priv) << Arg::Str(names->p_names_string) << Arg::Str(typeAsStr) << - Arg::Str(name)); + Arg::Str(fullName)); } } -void SCL_check_access(thread_db* tdbb, - const SecurityClass* s_class, - SLONG view_id, - SLONG obj_type, - const Firebird::MetaName& obj_name, - SecurityClass::flags_t mask, - SLONG type, - const Firebird::MetaName& name, - const Firebird::MetaName& r_name) -{ -/************************************** - * - * S C L _ c h e c k _ a c c e s s - * - ************************************** - * - * Functional description - * Check security class for desired permission. - * Alternate entrypoint. - * - **************************************/ - - SET_TDBB(tdbb); - - Firebird::string fullFieldName(name.c_str()); - if (r_name.hasData()) - { - fullFieldName = r_name.c_str(); - fullFieldName += '.'; - fullFieldName += name.c_str(); - } - - SCL_check_access(tdbb, s_class, view_id, obj_type, obj_name, mask, type, - fullFieldName.c_str()); -} - - void SCL_check_index(thread_db* tdbb, const Firebird::MetaName& index_name, UCHAR index_id, SecurityClass::flags_t mask) { @@ -388,20 +354,10 @@ WITH RF.RDB$RELATION_NAME EQ reln_name.c_str() AND ISEG.RDB$INDEX_NAME EQ idx_name_ptr->c_str() { - Firebird::string fullFieldName(reln_name.c_str()); - fullFieldName += '.'; - fullFieldName += RF.RDB$FIELD_NAME; - fullFieldName.rtrim(); - if (!RF.RDB$SECURITY_CLASS.NULL) - { - s_class = SCL_get_class(tdbb, RF.RDB$SECURITY_CLASS); - SCL_check_access(tdbb, s_class, 0, 0, NULL, mask, SCL_object_column, fullFieldName); - } - else - { - SCL_check_access(tdbb, default_s_class, 0, 0, NULL, mask, SCL_object_column, - fullFieldName); - } + s_class = (!RF.RDB$SECURITY_CLASS.NULL) ? + SCL_get_class(tdbb, RF.RDB$SECURITY_CLASS) : default_s_class; + SCL_check_access(tdbb, s_class, 0, NULL, NULL, mask, + SCL_object_column, RF.RDB$FIELD_NAME, reln_name); } END_FOR } @@ -661,7 +617,7 @@ const jrd_fld* field; SSHORT id; if (field_name && - (id = MET_lookup_field(tdbb, relation, field_name, 0)) >= 0 && + (id = MET_lookup_field(tdbb, relation, field_name)) >= 0 && (field = MET_get_field(relation, id)) && (s_class = SCL_get_class(tdbb, field->fld_security_name.c_str()))) { Modified: firebird/trunk/src/jrd/scl_proto.h =================================================================== --- firebird/trunk/src/jrd/scl_proto.h 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/scl_proto.h 2010-10-14 05:27:08 UTC (rev 51684) @@ -34,33 +34,8 @@ struct dsc; void SCL_check_access(Jrd::thread_db*, const Jrd::SecurityClass*, SLONG, SLONG, const Firebird::MetaName&, - Jrd::SecurityClass::flags_t, SLONG type, const char*); -void SCL_check_access(Jrd::thread_db*, const Jrd::SecurityClass*, SLONG, SLONG, const Firebird::MetaName&, Jrd::SecurityClass::flags_t, SLONG type, const Firebird::MetaName&, - const Firebird::MetaName&); -inline void SCL_check_access(Jrd::thread_db* tdbb, - const Jrd::SecurityClass* s_class, - SLONG view_id, - SLONG obj_type, - const Firebird::MetaName& obj_name, - Jrd::SecurityClass::flags_t mask, - SLONG type, - const Firebird::string& name) -{ - SCL_check_access(tdbb, s_class, view_id, obj_type, obj_name, mask, type, name.c_str()); -} -inline void SCL_check_access(Jrd::thread_db* tdbb, - const Jrd::SecurityClass* s_class, - SLONG view_id, - SLONG obj_type, - const Firebird::MetaName& obj_name, - Jrd::SecurityClass::flags_t mask, - SLONG type, - const Firebird::MetaName& name) -{ - SCL_check_access(tdbb, s_class, view_id, obj_type, obj_name, mask, type, name.c_str()); -} - + const Firebird::MetaName& = ""); void SCL_check_index(Jrd::thread_db*, const Firebird::MetaName&, UCHAR, Jrd::SecurityClass::flags_t); void SCL_check_package(Jrd::thread_db* tdbb, const dsc*, Jrd::SecurityClass::flags_t); void SCL_check_procedure(Jrd::thread_db* tdbb, const dsc*, Jrd::SecurityClass::flags_t); Modified: firebird/trunk/src/jrd/vio.cpp =================================================================== --- firebird/trunk/src/jrd/vio.cpp 2010-10-14 05:18:24 UTC (rev 51683) +++ firebird/trunk/src/jrd/vio.cpp 2010-10-14 05:27:08 UTC (rev 51684) @@ -3550,7 +3550,7 @@ Jrd::Attachment* attachment = tdbb->getAttachment(); SCL_check_access(tdbb, attachment->att_security_class, 0, 0, NULL, SCL_protect, - SCL_object_database, NULL); + SCL_object_database, ""); DFW_post_work(transaction, dfw_compute_security, &desc2, 0); } @@ -3573,7 +3573,7 @@ Jrd::Attachment* attachment = tdbb->getAttachment(); SCL_check_access(tdbb, attachment->att_security_class, 0, 0, NULL, SCL_control, - SCL_object_database, NULL); + SCL_object_database, ""); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <asf...@us...> - 2010-12-05 00:55:00
|
Revision: 52025 http://firebird.svn.sourceforge.net/firebird/?rev=52025&view=rev Author: asfernandes Date: 2010-12-05 00:54:54 +0000 (Sun, 05 Dec 2010) Log Message: ----------- Make expression evaluation faster Modified Paths: -------------- firebird/trunk/src/jrd/evl.cpp firebird/trunk/src/jrd/evl_proto.h Modified: firebird/trunk/src/jrd/evl.cpp =================================================================== --- firebird/trunk/src/jrd/evl.cpp 2010-12-04 22:15:03 UTC (rev 52024) +++ firebird/trunk/src/jrd/evl.cpp 2010-12-05 00:54:54 UTC (rev 52025) @@ -295,30 +295,6 @@ } -// Evaluate a value expression. -dsc* EVL_expr(thread_db* tdbb, jrd_req* request, const ValueExprNode* node) -{ - if (!node) - BUGCHECK(303); // msg 303 Invalid expression for evaluation - - SET_TDBB(tdbb); - - if (--tdbb->tdbb_quantum < 0) - JRD_reschedule(tdbb, 0, true); - - request->req_flags &= ~req_null; - - dsc* desc = node->execute(tdbb, request); - - if (desc) - request->req_flags &= ~req_null; - else - request->req_flags |= req_null; - - return desc; -} - - bool EVL_field(jrd_rel* relation, Record* record, USHORT id, dsc* desc) { /************************************** Modified: firebird/trunk/src/jrd/evl_proto.h =================================================================== --- firebird/trunk/src/jrd/evl_proto.h 2010-12-04 22:15:03 UTC (rev 52024) +++ firebird/trunk/src/jrd/evl_proto.h 2010-12-05 00:54:54 UTC (rev 52025) @@ -25,6 +25,7 @@ #define JRD_EVL_PROTO_H #include "../jrd/intl_classes.h" +#include "../jrd/req.h" namespace Jrd { @@ -35,9 +36,34 @@ dsc* EVL_assign_to(Jrd::thread_db* tdbb, const Jrd::ValueExprNode*); Jrd::RecordBitmap** EVL_bitmap(Jrd::thread_db* tdbb, const Jrd::InversionNode*, Jrd::RecordBitmap*); -dsc* EVL_expr(Jrd::thread_db* tdbb, Jrd::jrd_req* request, const Jrd::ValueExprNode* node); bool EVL_field(Jrd::jrd_rel*, Jrd::Record*, USHORT, dsc*); void EVL_make_value(Jrd::thread_db* tdbb, const dsc*, Jrd::impure_value*); void EVL_validate(Jrd::thread_db*, const Jrd::Item&, const Jrd::ItemInfo*, dsc*, bool); +namespace Jrd +{ + // Evaluate a value expression. + inline dsc* EVL_expr(thread_db* tdbb, jrd_req* request, const ValueExprNode* node) + { + if (!node) + BUGCHECK(303); // msg 303 Invalid expression for evaluation + + SET_TDBB(tdbb); + + if (--tdbb->tdbb_quantum < 0) + JRD_reschedule(tdbb, 0, true); + + request->req_flags &= ~req_null; + + dsc* desc = node->execute(tdbb, request); + + if (desc) + request->req_flags &= ~req_null; + else + request->req_flags |= req_null; + + return desc; + } +} + #endif // JRD_EVL_PROTO_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <hv...@us...> - 2010-12-17 22:32:41
|
Revision: 52053 http://firebird.svn.sourceforge.net/firebird/?rev=52053&view=rev Author: hvlad Date: 2010-12-17 22:32:35 +0000 (Fri, 17 Dec 2010) Log Message: ----------- Frontport better fix for bug CORE-3266 : Race condition between async service detach request and running user trace service Modified Paths: -------------- firebird/trunk/src/jrd/svc.cpp firebird/trunk/src/jrd/svc.h firebird/trunk/src/jrd/trace/TraceService.cpp Modified: firebird/trunk/src/jrd/svc.cpp =================================================================== --- firebird/trunk/src/jrd/svc.cpp 2010-12-17 09:54:17 UTC (rev 52052) +++ firebird/trunk/src/jrd/svc.cpp 2010-12-17 22:32:35 UTC (rev 52053) @@ -936,7 +936,15 @@ ULONG Service::totalCount() { MutexLockGuard guard(globalServicesMutex); - return allServices->getCount(); + AllServices& all(allServices); + ULONG cnt = 0; + + // don't count already detached services + for (size_t i = 0; i < all.getCount(); i++) + if (!(all[i]->svc_flags & SVC_detached)) + cnt++; + + return cnt; } @@ -967,7 +975,14 @@ MutexLockGuard guard(globalServicesMutex); AllServices& all(allServices); - for (unsigned int pos = 0; pos < all.getCount(); ) + unsigned int pos; + + // signal once for every still running service + for (pos = 0; pos < all.getCount(); pos++) + if (all[pos]->svc_flags & SVC_thd_running) + all[pos]->svc_detach_sem.release(); + + for (pos = 0; pos < all.getCount(); ) { if (all[pos]->svc_flags & SVC_thd_running) { @@ -2281,6 +2296,10 @@ { svc_flags &= ~SVC_thd_running; } + else + { + svc_detach_sem.release(); + } } } Modified: firebird/trunk/src/jrd/svc.h =================================================================== --- firebird/trunk/src/jrd/svc.h 2010-12-17 09:54:17 UTC (rev 52052) +++ firebird/trunk/src/jrd/svc.h 2010-12-17 22:32:35 UTC (rev 52053) @@ -290,6 +290,8 @@ Firebird::Mutex mtx; }; + Firebird::Semaphore svc_detach_sem; + private: StatusStringsHelper svc_thread_strings; Modified: firebird/trunk/src/jrd/trace/TraceService.cpp =================================================================== --- firebird/trunk/src/jrd/trace/TraceService.cpp 2010-12-17 09:54:17 UTC (rev 52052) +++ firebird/trunk/src/jrd/trace/TraceService.cpp 2010-12-17 22:32:35 UTC (rev 52053) @@ -284,7 +284,8 @@ if (!checkAliveAndFlags(session.ses_id, flags)) break; - THD_sleep(250); + if (m_svc.svc_detach_sem.tryEnter(0, 250)) + break; } else { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <di...@us...> - 2011-01-16 08:42:49
|
Revision: 52138 http://firebird.svn.sourceforge.net/firebird/?rev=52138&view=rev Author: dimitr Date: 2011-01-16 08:42:42 +0000 (Sun, 16 Jan 2011) Log Message: ----------- Misc. Modified Paths: -------------- firebird/trunk/src/jrd/Optimizer.cpp firebird/trunk/src/jrd/Optimizer.h firebird/trunk/src/jrd/opt.cpp Modified: firebird/trunk/src/jrd/Optimizer.cpp =================================================================== --- firebird/trunk/src/jrd/Optimizer.cpp 2011-01-16 03:39:49 UTC (rev 52137) +++ firebird/trunk/src/jrd/Optimizer.cpp 2011-01-16 08:42:42 UTC (rev 52138) @@ -633,7 +633,7 @@ node->computable(csb, stream, false, true) && !invCandidate->matches.exist(node)) { - const ComparativeBoolNode* cmpNode = node->as<ComparativeBoolNode>(); + const ComparativeBoolNode* const cmpNode = node->as<ComparativeBoolNode>(); const double factor = (cmpNode && cmpNode->blrOp == blr_eql) ? REDUCE_SELECTIVITY_FACTOR_EQUALITY : REDUCE_SELECTIVITY_FACTOR_INEQUALITY; @@ -2416,6 +2416,7 @@ stream = 0; unique = false; cost = 0; + cardinality = 0; } @@ -2562,8 +2563,10 @@ CompilerScratch::csb_repeat* csb_tail = &csb->csb_rpt[innerStreams[i]->stream]; csb_tail->csb_flags |= csb_active; - OptimizerRetrieval optimizerRetrieval(pool, optimizer, innerStreams[i]->stream, false, false, NULL); + OptimizerRetrieval optimizerRetrieval(pool, optimizer, innerStreams[i]->stream, + false, false, NULL); AutoPtr<InversionCandidate> candidate(optimizerRetrieval.getCost()); + innerStreams[i]->baseCost = candidate->cost; innerStreams[i]->baseIndexes = candidate->indexes; innerStreams[i]->baseUnique = candidate->unique; @@ -2678,8 +2681,8 @@ // Create the optimizer retrieval generation class and calculate // which indexes will be used and the total estimated selectivity will be returned OptimizerRetrieval optimizerRetrieval(pool, optimizer, stream, false, false, NULL); + AutoPtr<const InversionCandidate> candidate(optimizerRetrieval.getCost()); - AutoPtr<const InversionCandidate> candidate(optimizerRetrieval.getCost()); *cost = candidate->cost; // Calculate cardinality @@ -2699,7 +2702,7 @@ * * Find the best order out of the streams. * First return a stream if it can't use - * a index based on a previous stream and + * an index based on a previous stream and * it can't be used by another stream. * Next loop through the remaining streams * and find the best order. Modified: firebird/trunk/src/jrd/Optimizer.h =================================================================== --- firebird/trunk/src/jrd/Optimizer.h 2011-01-16 03:39:49 UTC (rev 52137) +++ firebird/trunk/src/jrd/Optimizer.h 2011-01-16 08:42:42 UTC (rev 52138) @@ -214,10 +214,10 @@ public: IndexRelationship(); - int stream; - bool unique; - double cost; - double cardinality; + int stream; + bool unique; + double cost; + double cardinality; }; typedef Firebird::Array<IndexRelationship*> IndexedRelationships; @@ -228,12 +228,12 @@ explicit InnerJoinStreamInfo(MemoryPool& p); bool independent() const; - int stream; - bool baseUnique; - double baseCost; - int baseIndexes; - int baseConjunctionMatches; - bool used; + int stream; + bool baseUnique; + double baseCost; + int baseIndexes; + int baseConjunctionMatches; + bool used; IndexedRelationships indexedRelationships; int previousExpectedStreams; Modified: firebird/trunk/src/jrd/opt.cpp =================================================================== --- firebird/trunk/src/jrd/opt.cpp 2011-01-16 03:39:49 UTC (rev 52137) +++ firebird/trunk/src/jrd/opt.cpp 2011-01-16 08:42:42 UTC (rev 52138) @@ -1642,8 +1642,8 @@ // depends on already active streams and can not be used in a separate // SORT/MERGE. - OptimizerRetrieval optimizerRetrieval(*tdbb->getDefaultPool(), opt, *stream, false, false, NULL); - + OptimizerRetrieval optimizerRetrieval(*tdbb->getDefaultPool(), opt, *stream, + false, false, NULL); AutoPtr<InversionCandidate> candidate(optimizerRetrieval.getCost()); if (candidate->dependentFromStreams.hasData()) @@ -1744,15 +1744,12 @@ if (temp[0] != 0) { - OptimizerInnerJoin* const innerJoin = FB_NEW(*tdbb->getDefaultPool()) - OptimizerInnerJoin(*tdbb->getDefaultPool(), opt, temp, sort_clause, plan_clause); - USHORT count; + OptimizerInnerJoin innerJoin(*tdbb->getDefaultPool(), opt, temp, sort_clause, plan_clause); + USHORT count; do { - count = innerJoin->findJoinOrder(); + count = innerJoin.findJoinOrder(); } while (form_river(tdbb, opt, count, streams[0], temp, river_list, sort_clause)); - - delete innerJoin; } } @@ -1955,18 +1952,15 @@ return; } - OptimizerInnerJoin* const innerJoin = FB_NEW(*tdbb->getDefaultPool()) - OptimizerInnerJoin(*tdbb->getDefaultPool(), opt, streams, sort_clause, plan_clause); + OptimizerInnerJoin innerJoin(*tdbb->getDefaultPool(), opt, streams, sort_clause, plan_clause); stream_array_t temp; memcpy(temp, streams, streams[0] + 1); USHORT count; do { - count = innerJoin->findJoinOrder(); + count = innerJoin.findJoinOrder(); } while (form_river(tdbb, opt, count, streams[0], temp, river_list, sort_clause)); - - delete innerJoin; } @@ -2233,8 +2227,8 @@ else { // Persistent table - OptimizerRetrieval optimizerRetrieval(*tdbb->getDefaultPool(), - opt, stream, outer_flag, inner_flag, sort_ptr); + OptimizerRetrieval optimizerRetrieval(*tdbb->getDefaultPool(), opt, stream, + outer_flag, inner_flag, sort_ptr); AutoPtr<InversionCandidate> candidate(optimizerRetrieval.getInversion(&nav_rsb)); if (candidate && candidate->inversion) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |