Индексы быстрого приготовления

Эти функции пригодятся, когда нужно на скорую руку построить индексы в произвольном нарастании/убывании, по полям разных типов в VFP или FPD, или почему-то "правильный" индекс не работает.

Индексы быстрого приготовления

*******************************************************************
* Индексы быстрого приготовления *
* *
* 1. Назначение *
* Нередко возникает задача создания сложного индекса, содержащего *
* поля таблицы разных типов. В общем случае эта задача не имеет *
* однозначного решения, зато в ней имеются забавные подвохи. *
* Предлагаемое решение позволяет строить индексы, даже не *
* зная типов используемых переменных и полей таблицы. Плюс *
* произвольно назначать нарастание/убывание для любого поля, *
* входящего в индекс. При желании можно оптимизировать исходные *
* функции для собственных целей. Для маломерных таблиц *
* оптимизация и не потребуется. *
* *
* 2. Структура программы *
* 2.1. Создаются вспомогательные константы. *
* 2.2. Синтезируется тестовая таблица на 100 000 записей, *
* заполненная случайными значениями. *
* 2.3. Таблица индексируется. *
* 2.4. Индексированная таблица копируется во вторую таблицу для *
* удобства просмотра. *
* 2.5. Тестовые файлы и папка удаляются. *
* *
* 3. Прочее *
* 3.1. Предусмотрена работа под FoxPRO 2...8 *
* *
* 4. Благодарности принимаютсяна ник GoodMan *
* *
* *
******************** 13 апреля 2004 *******************************

SET CENTURY ON
SET TALK OFF
SET ECHO OFF
SET DATE ANSI
SET HOURS TO 24
SET BLOCKSIZE TO 64
SET PROCEDURE TO myindex
PUBLIC records_in_sample
records_in_sample=100000 && число записей в тестовой таблице

DO dbfsample && изготовление тестовой таблицы
DO charset && подготовка вспомогательных символьных констант

SET DEFAULT TO C:_myindex
SELECT 1

INDEX ON (descend1("char_1")+ascend1("logic_1")+descend1("numer_1"));
;
TO myindex.cdx COMPACT

COPY TO dbf2
SELECT 2
USE dbf2
CLEAR
BROWSE LAST

DO goodby && удаление тестовых файлов и папки C:_MYINDEX

*QUIT

*--ASCEND1***********************************
* преобразование аргумента в текстовую *
* константу с характеристикой ASCENDING *
*********************************************
FUNCTION ascend1
PARAMETER cur_obj
PRIVATE cur_obj, obj_type, obj_value
obj_type=TYPE(cur_obj)
DO CASE
CASE (obj_type $ "CM") && идентификация аргументов CHAR и MEMO
obj_value=LEFT(ALLTRIM(LEFT(&cur_obj,254)),20)
CASE (obj_type $ "NY") && идентификация аргументов NUMERIC и CURRENCY
Cur_obj=&cur_obj
DO CASE
CASE cur_obj>0
Obj_value=PADL(STR(LOG(cur_obj)+3000,12,7),12,"0")
CASE cur_obj=0
Obj_value="2000.0000000"
CASE cur_obj<0
Obj_value=PADL(STR(-LOG(-cur_obj)+1000,12,7),12,"0")
ENDCASE
CASE (obj_type $ "D") && идентификация аргументов DATE
Obj_value=DTOC(&cur_obj)
CASE (obj_type $ "T") && идентификация аргументов DATETIME
Obj_value=TTOC(&cur_obj)
CASE (obj_type $ "L") && идентификация аргументов LOGICAL
Obj_value= IIF(&cur_obj=.F., "_0_", "_1_")
OTHERWISE
Obj_value=" "
ENDCASE
RETURN obj_value

*--DESCEND1**********************************
* преобразование аргумента в текстовую *
* константу с характеристикой DESCENDING *
*********************************************

PROCEDURE descend1
PARAMETER cur_obj
PRIVATE cur_obj, obj_type, obj_value
obj_type=TYPE(cur_obj)
DO CASE
CASE (obj_type $ "CM") && идентификация аргументов CHAR и MEMO
obj_value=CHRTRAN(LEFT(ALLTRIM(LEFT(&cur_obj,254)),20),char_up,char_down)
CASE (obj_type $ "NY") && идентификация аргументов NUMERIC и CURRENCY
Cur_obj=&cur_obj
DO CASE
CASE cur_obj>0
Obj_value=PADL(STR(-LOG(cur_obj)+1000,12,7),12,"0")
CASE cur_obj=0
Obj_value="2000.0000000"+REPLICATE("0",12)
CASE cur_obj<0
Obj_value=PADL(STR(LOG(-cur_obj)+3000,12,7),12,"0")
ENDCASE
CASE (obj_type $ "D") && идентификация аргументов DATE
Obj_value=CHRTRAN(DTOC(&cur_obj),"0123456789","9876543210")
CASE (obj_type $ "T") && идентификация аргументов DATETIME
Obj_value=CHRTRAN(TTOC(&cur_obj),"0123456789","9876543210")

CASE (obj_type $ "L") && идентификация аргументов LOGICAL
Obj_value= IIF(&cur_obj=.T., "_0_", "_1_")
OTHERWISE
Obj_value=" "
ENDCASE
RETURN obj_value

*--charset ************************************
* изготовление бинарно дополнительных наборов *
* символов (CHR(0)...CHR(255)) и *
* (CHR(255)...CHR(0)) для инверсии текстовых *
* констант *
***********************************************
PROCEDURE charset
PUBLIC char_up, char_down
PRIVATE i2

STORE "" TO char_up, char_down
i2=0
DO WHILE i2 < 256
Char_up=char_up+CHR(i2)
Char_down=char_down+CHR(255-i2)
I2=i2+1
ENDDO
RETURN

*--dbfsample ****************************
* изготовление тестовой таблицы с *
* разнообразными полями и заполнение их *
* случайными значениями *
*****************************************
PROCEDURE dbfsample
! CD C:
! MD C:_myindex
SET DEFAULT TO C:_myindex

PRIVATE i1

SELECT 1

* определим версию FOXa ...
fox_version=VAL(CHRTRAN(VERSION( ), " ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ ;
"abcdefghijklmnopqrstuvwxyz",""))

DO CASE
CASE (fox_version >= 3)
* Делаем тестовую таблицу для VFP 3...8...
CREATE TABLE MYINDEX ;
( logic_1 L( 1), ;
char_1 C( 10), ;
numer_1 N(15,3), ;
curren_1 Y( 8), ;
memo_1 M , ;
date_1 D( 4), ;
datetime_1 T( 8) )

USE C:_myindexmyindex

tmp=RAND(-1)
i1=1

DO WHILE i1 <= records_in_sample
APPEND BLANK
rand_char= REPLICATE(CHR(RAND( )*255.9),20)
REPLACE char_1 WITH rand_char
REPLACE memo_1 WITH rand_char

rand_num=EXP(RAND( )*25-1) * IIF(RAND()<0.5, -1 , 1)
rand_num=IIF(BETWEEN(rand_num,50,100),0,rand_num)
REPLACE numer_1 WITH rand_num
REPLACE curren_1 WITH rand_num

Date_base={^0100-01-02,01:23:45}
REPLACE date_1 WITH (Date_base+RAND( )*1000000*3600*24)
REPLACE datetime_1 WITH (Date_base+RAND( )*1000000*3600*24)
REPLACE logic_1 WITH IIF((RAND( )-0.5)>0, .T., .F.)
i1=i1+1
IF (MOD(i1,10000)=0)
? " "+STR(i1)+" ЗАПИСЕЙ СИНТЕЗИРОВАНО"
ENDIF
ENDDO
* Делаем тестовую таблицу для FPD/FPW 2.0 ... 2.6
CASE (fox_version < 3)
CREATE TABLE MYINDEX ;
( logic_1 L( 1), ;
char_1 C( 10), ;
numer_1 N(15,3), ;
memo_1 M , ;
date_1 D (8) )

USE C:_myindexmyindex

tmp=RAND(-1)
i1=1

DO WHILE i1 <= records_in_sample
APPEND BLANK
rand_char= REPLICATE(CHR(RAND( )*255.9),20)
REPLACE char_1 WITH rand_char
REPLACE memo_1 WITH rand_char

rand_num=EXP(RAND( )*25-1) * IIF(RAND()<0.5, -1 , 1)
rand_num=IIF(BETWEEN(rand_num,50,100),0,rand_num)
REPLACE numer_1 WITH rand_num
SET DATE ANSI
Date_base=CTOD("01.01.01")
Date_base=Date_base+(RAND( )-0.5)*500000
REPLACE date_1 WITH Date_base
REPLACE logic_1 WITH IIF((RAND( )-0.5)>0, .T., .F.)
i1=i1+1
IF (MOD(i1,10000)=0)
? " "+STR(i1)+" ЗАПИСЕЙ СИНТЕЗИРОВАНО"
ENDIF
ENDDO

ENDCASE
FLUSH
CLEAR
@ 20,20 SAY "ВСЕГО "+STR(i1-1)+" ЗАПИСЕЙ В ТАБЛИЦЕ"
WAIT "" timeout 3.0
CLEAR
@ 20,20 SAY "ТАБЛИЦА ИНДЕКСИРУЕТСЯ . . ."

RETURN

*--goodby *******************************
* чистим тестовые файлы и папки *
*****************************************
PROCEDURE goodby
CLOSE ALL
CLEAR ALL
! DEL C:_myindex*.dbf
! DEL C:_myindex*.fpt
! DEL C:_myindex*.cdx
! RD C:_myindex
RETURN

Автор: GoodMan
0

Автор публикации

не в сети 20 лет

GoodMan

0
Комментарии: 0Публикации: 1Регистрация: 04-03-2004
Оставить комментарий
Авторизация
*
*
Генерация пароля