Форум » [x]Harbour » Как прицепится к ADS по сети ? » Ответить

Как прицепится к ADS по сети ?

Dima: Есть ADS 10.10 в настройках у него стоит порт 6262 Вот таким исходником пытаюсь к нему подрубиться. [pre2] #include "ads.ch" proc main REQUEST ADS rddSetDefault( "ADSCDX" ) SET SERVER REMOTE SET CHARTYPE TO OEM ? AdsConnect("MYSERVER") // .f. ? AdsConnect("//127.0.0.1/:6262") // .f. return [/pre2] ADS.INI в папке с прогой [pre2] [MYSERVER] LAN_IP=127.0.0.1 LAN_PORT=6262 [/pre2] Где мой косяк ?

Ответов - 257, стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 All

PSP: Может так: AdsConnect("//127.0.0.1:6262") ? И, эта, 127.0.0.1 - это локальный компьютер. АДС на нем же запущен?

Dima: Dima пишет: 127.0.0.1 С таким адресом похоже он не пашет. Разобрался. Задал реальный адрес и заработало. А как мне правильно открыть базу которая лежит в C:\TEST\DBF\KARTA.DBF по IP и порту заданному в ADS.INI ? Может чего надо прописать в ADS.INI....

Dima: PSP пишет: АДС на нем же запущен? Да


Dima: PSP пишет: Может так: AdsConnect("//127.0.0.1:6262") ? Точно. Так работает. Спасибо. Глазик замылился ;) А как базу открыть ?

PSP: Дим, я с АДС не работал. Сорри...

Pasha: Когда я работал с ads. обязательно надо было расшаривать сетевой ресурс, и при открытии указывать имя файла в формате unc. Можно еще использовать data dictionary. но с ним я не работал. Если еще AIS, там конечно расшаривать ничего не надо, так как это сделать невозможно, но с ним я опять таки не работал.

Dima: Все таки нашел путь ;) В ASD.INI Делаем [pre2] [DRIVES] x:=//127.0.0.1/C$/sklad/dbf/ [/pre2] А в проге USE x:karta Можно и так Set path to x: use karta ЗЫ При чем расшаривать не надо (буква X: в проводнике не появится) Интересно в ADS есть похожие вещи как в LETO ? LETO_VARSET LETO_VARGET LETO_VARDEL

Pasha: Dima пишет: [DRIVES] x:=//127.0.0.1/C$/sklad/dbf/ А если доступ c$ закрыт, работать будет ? В доке, правда к ads 9.x, написано: [DRIVES] If you wish to connect to the Advantage Database Server via the Advantage Internet Server, and your application uses drive letters, you will need a [DRIVES] section to contain the information needed for an Internet connection to Advantage. The [DRIVES] section should contain a list of all drive letters used by the application and the server name and share (or volume) in which the drive letter should map on the server in which the Advantage Database Server is running. The server name and share (or volume) should be UNC (\\SERVERNAME\SHARE).

Dima: Pasha У меня служба доступа к файлам и принтерам вообще выключена и ни чего не расшарено. А попробуй у себя в браузере строку вбить [pre2] \\127.0.0.1\c$ [/pre2] Правда если сделать вот так net share c$ /delete то доступа не будет

Dima: А есть ли возможность в ADS управлять переменными как в LETO ? Или может какой то похожий инструмент там есть ? Есть там семафоры но как ими управлять ХЗ

Dima: Вопросец нарисовался. Папка с выполняемым файлом лежит на серваке и расшарена. Все рабочие станции юзают этот расшаренный EXE. Такая схема вполне работоспособна еще со времен Clipper. НО в этой же папке лежат и файлики которые нужны для работы ace32.dll axcws32.dll Не будет ни каких конфликтов с этими DLL и будут ли они цепляться при таком подходе при загрузке программы ?

Dima: Ответ как бы сам меня нашел ;) Запустил прогу. После этого убил выполняемый файл и оба DLL , прога нормально функционирует. Значит при загрузке программы и прога и DLL грузятся в память. Что интересно такой фокус с удалением для Clipper EXEшника не работает.

nick_mi: Странно, я не могу удалить EXE файл, когда он работает, заметил еще во время перекомпиляции программы. Удалять DLL во время работы программы не пробовал. А вообще у нас изначально все программы запускаются из расшаренного диска, правда пока у нас вся система крутится на серверах NOWELL и ADS. Полностью на Windows сервера может быть начнем переходить осенью

Dima: Как работать с ADS в локальной сети понятно. Встала задача работать с этой же базой через инет. С чего тут правильно начать ? В самом ADS прописать инет порт это ясно В проге установить AdsSetServerType(4) Пробую цеплятся AdsConnect(инетIPадрес+порт) и глухо

Dima: Dima пишет: Пробую цеплятся AdsConnect(инетIPадрес+порт) и глухо Разобрался. Хорошо есть где почитать. Например тут Cоздал DATADICTIONARY c помощью Advantage Data Architect , и разрешил юзать базу по инету. В итоге подключился , базы открываются , все как бы красиво. Но возник вопрос как быть с файловыми операциями. Как минимум нужны Ferase(), Fopen(),Directory(),Fcreate(),File() Из аналогов в ADS нашел только три: AdsDirectory() , AdsDeleteFile(),AdsCheckExistence() (аналог File()) Маловато будет. Что же делать ?

Haz: Dima, Удалось подключиться через инет ? возникла мысль может это с типом таблиц связано, не уверен в этом , но вот что есть в хелпе по ADS Advantage Client Engine API To connect to an Advantage Database Server over the Internet using the Advantage Client Engine API, you will need to call AdsConnect60 with the full path to the data dictionary and with ADS_AIS_SERVER as the second parameter or as part of the second parameter. Example: ulRetVal = AdsConnect60( "q:\\test.add", ADS_AIS_SERVER, "User1", "foobar", ADS_DEFAULT, &hConnect );

Dima: Haz пишет: Удалось подключиться через инет ? Да только не хватает мне файловых операций. Нормального аналога функции File() нет , похожий аналог AdsCheckExistence() совсем не аналог оказался ;) Тупо ищет только *.dbf при чем только те что объявлены в DATADICTIONARY. Файл семафора создать тоже не могу так как ни проверить его существование ни создать не выходит. Молчу уже про MakeDir() , нормальный Directory() и тд и тп В этом плане LetoDB намного гибче

Dima: Насчет файловых операций. [pre2] First thing you have to understand when using AIS (advantage internet server) is that you are not having access to a file server directory, only to the database, so you cannot perform any activity related with OS file operations, for example you cannot make a FILE() or FCOPY() operation, you cannot create tables (unless you do it via SQL). [/pre2]

pureproft: Если нет желания или возможности написать что то параллельно работающее и получающее задание по ip, то я в таких случаях на удалённом офисе(т.е. чуть шире чем сервере) пишу и запускаю что то ожидающее заданий в вашем случае в таблицах ADS(например по таймауту проверяющее их наличие) и в них же отчитывающееся о успешном или нет выполнении оных, таким образом можно даже ОС переустановить в удалённом офисе где то в интернете

Pasha: В харборе на этот случай есть драйвер netio. Можно собрать netio-сервер, запустить его как приложение, и клиент может обращаться к нему с запросами по файловым операциям. А в качестве запросов будут собственно вызовы обычных файловых функций, для memio мы их разбирали: FErase("netio:" + ...) и так далее только File() мне кажется так работать не будет, но ей можно найти замену, та же Directory, или FileSeek(), или что-то еще

Dima: Pasha Да я думал над этим вариантом. Просто считал что есть в ADS удаленные файловые функции как в LetoDB , но оказалось их нет.

Dima: Pasha пишет: только File() мне кажется так работать не будет Работает если Netio cервер собрать с request file (проверил) , говорю о netio_funcexec с функцией File

Dima: хмм... в ADS так и осталось ограничение на кол-во индексных файлов для рабочей области (15 штук) ? http://devzone.advantagedatabase.com/dz/webhelp/Advantage7.1/server1/xbase_file_format_specifications.htm

PSP: Dima пишет: в ADS так и осталось ограничение на кол-во индексных файлов для рабочей области (15 штук) ... и в каждом может быть до 50-ти ордеров, не?

Dima: PSP пишет: не? Да , но не могу юзать CDX так как не возможно выключить AUTOPEN и тогда при открытии базы с индексами может быть бяка. Use TEST INDEX TEST1,TEST new Индекс TEST заявлен вторым по счету а на деле будет первым.......

azoo: С ADS не работал. Не получается откомпилить пример. Выдает ошибки: Error: Unresolved external '_HB_FUN_ADSSETSERVERTYPE' referenced Error: Unresolved external '_HB_FUN_ADSSETCHARTYPE' referenced fr Error: Unresolved external '_HB_FUN_ADSCONNECT' referenced from C Error: Unresolved external '_HB_FUN_ADS' referenced from C:\ADS\X Какую LIB подключить?

Dima: azoo пишет: Какую LIB подключить? rddads и ace32

azoo: Почему-то ace32.lib нет в библиотеках HB30. Нашёл в xHarbour. Теперь пишет: Error: Unresolved external 'AdsGetFieldW' referenced from C:\HB30\LIB\WIN\BCC\RD DADS.LIB|ads1 Error: Unresolved external 'AdsGetStringW' referenced from C:\HB30\LIB\WIN\BCC\R DDADS.LIB|ads1 Error: Unresolved external 'AdsSetStringW' referenced from C:\HB30\LIB\WIN\BCC\R DDADS.LIB|ads1 Только после того, как скопировал rddads.lib из xHarbour в папку C:\HB30\LIB\WIN\BCC смог скомпилировать. Но при запуске программа выдаёт ошибку: Error BASE/1001 Undefined function: ADT_GETFUNCTABLE Called from ADT_GETFUNCTABLE(0)

Dima: azoo пишет: Почему-то ace32.lib Надо скачать ACE http://devzone.advantagedatabase.com/dz/content.aspx?key=20&Release=19&Product=5&Platform=6 и установить. Пересобрать RDDADS указав пути к ACE в set HB_DIR_ADS=C:\ваш путь\acesdk set HB_WITH_ADS=C:\ваш путь\acesdk после того как соберешь в папку с прогой сложи adslocal.cfg ansi.chr extend.chr ace32.dll adsloc32.dll axcws32.dll

azoo: Спасибо получилось. Способ с подключением через ЛВС без расшаривания ресурса работает. Только .ntx не подключаются к сожалению.

Dima: azoo пишет: Только .ntx не подключаются к сожалению. rddSetDefault( "ADSNTX" )

azoo: Ещё несколько вопросов по ADS в [x]Harbour. в Harbour_Manual.chm есть описание функций, начинающихся ADS......(), например ADSblob2file(). там есть ссылка на некий файл ACE.HLP, который искал но не смог найти. Вопрос такой: работать с ADS из Harbour можно только стандартными Clipper-командами или есть какие-то специальные команды для этого. Например в Clipper были команды AX_......(). Их можно использовать в Harbour ?

Dima: azoo пишет: там есть ссылка на некий файл ACE.HLP, который искал но не смог найти. Используй advantage.chm который в составе ADS идет Функций типа AX_ уже нет , поэтому нужно искать аналоги в RDDADS если они есть конечно. Лучше всего посмотреть advantage.chm и сырцы rddads azoo пишет: Вопрос такой: работать с ADS из Harbour можно только стандартными Clipper-командами или есть какие-то специальные команды для этого. Можно и так и сяк

azoo: Dima я так понял что [x]Harbour с ADS не совсем дружен в отличие от Clipper. Причина конечно в официальной поддержке Sybase интерфейса с Clipper.

Dima: azoo Смотря что понимать под такой дружбой. Свое приложение с Clipper+ADS я перевел нормально под Harbour+ADS. Говори конкретнее что интересует.

azoo: Приложение Clipper+ADS было написано без использования каких-либо функций AX_() ?

Dima: azoo пишет: Приложение Clipper+ADS было написано без использования каких-либо функций AX_() ? У меня ? Конечно с их использованием ! На вскидку что юзал ax_driver AX_GetAOFRecordCount ax_keyno ax_getaofexpr AX_CacheRecords AX_Loaded AX_GetDrive ax_error Ax_SetServerAOF ax_clearserveraof и тд и тп

azoo: Ну и... чем были заменены AX_() функции в Harbour ?

Dima: azoo пишет: Ну и... чем были заменены AX_() функции в Harbour ? А есть аналоги в ACE SDK не все правда.

Dima: azoo Спрашивай конкретно. Когда я переводил приложение с Clipper(ADS) тоже не мог найти ряд аналогов. Копал доку , смотрел ченжлог и если решения не видел спрашивал тут на форуме. Поможем чем сможем , вопросы задавай.

azoo: Хотелось бы перевести проекты Clipper+DBF на Harbour+ADS. Опыта работы с ADS нет. Есть ли доки по ADS, которые можно использовать для работы с Harbour+ADS ?

Dima: azoo Есть примеры в RddAds , есть форум на котором поиск работает. Начни делать что то а появятся вопросы на которые ответа не найдешь , спрашивай на форуме.

azoo: Dima а возможно ли полностью уйти от DBF ?

Dima: azoo пишет: Dima а возможно ли полностью уйти от DBF ? Да если мы говорим о связке с ADS , в нем есть собственный формат данных ADT Правда я сижу на DBF , во всяком случае пока. Почитать http://devzone.advantagedatabase.com/dz/WebHelp/Advantage11.1/index.html?master_adt_field_types_and_specifications.htm http://devzone.advantagedatabase.com/dz/WebHelp/Advantage11.1/index.html?ace_supported_file_formats.htm

Dr. Oldwarez: И меня эта тема очень интересует. LetoDB не предлагать - не люблю собирать из исходников. Я так надеялся на ADS, а теперь выясняется, что ADS тоже глючит. У меня локальная сеть в 4 клиента+сервер.

Dima: Dr. Oldwarez пишет: Я так надеялся на ADS, а теперь выясняется, что ADS тоже глючит В чем например ? Можно ведь и официально его купить и иметь офф поддержку. Что касается сборки LetoDB сложного там нет ни чего , если нужно выложу уже готовый вариант.

Dr. Oldwarez: Dima пишет: Что касается сборки LetoDB сложного там нет ни чего , если нужно выложу уже готовый вариант. Большое спасибо Под винду и BCC

Dima: Dr. Oldwarez http://rghost.ru/49283904 PS Winrar 5.0 Bcc582

vladru: У меня появилась задача переделать приложение из Clipper+(ADS NovellNetware) на Harbour. Раньше с Novell никогда дела не имел. Дома поставил ADS+ACE 9.10 и harbour собрал с этим ACE. Тестовое приложение из топика без проблем коннектится к MYSERVER Стал разбираться с Novell - никак не подключиться. 1) владелец сервера мне разъяснил что протокол IPX и никаких IP у сервера нет 2) у них доступ к серверу по букве (z:) или (\\Server) 3) в advantage.chm/AdsConnect написано что в Novell надо по "volume name for Novell NetWare " подключаться... пробую: ? AdsConnect("Z:") // .F. ? AdsConnect("\\Server") // .F. Версия сервера у них 5.X. А у меня клиент 9.1. Может из-за этого проблемы... Подскажите, если можно с примером, как к ADS ON Novell подключиться?

Dima: vladru пишет: Версия сервера у них 5.X. А у меня клиент 9.1. Может из-за этого проблемы... ACE нужен 5.x Держи http://gfile.ru/a26Um

vladru: Спасибо. (Это тот что на форуме в ветке "имя алиаса" мелькал ?) Ну естсественно мой .exe с этим ACE вылетает по ошибке в ace32.dll Вопрос: Мне теперь надо harbour пересобрать указав в качестве acesdk содержимое этого архива ? А после этого этот клиент будет к моему домашнему win-ADS 9.1 подключаться или сервер то же нужен 5.x ?

Dima: Версия ADS должна совпадать с версией ACE Пересобрать нужно только RDDADS

vladru: Dima пишет: Версия ADS должна совпадать с версией ACE Где же мне такого старого зверя под win найти поможите кто чем можете... Dima пишет: Пересобрать нужно только RDDADS Намекните как это сделать, не пересобирая весь harbour по win-make (ил где почитать) и последнее, всё-же скажите пожалуйста нубо- новеллу как мне к ADS-Novell подключаться ? по имени диска ?

Dima: vladru пишет: Где же мне такого старого зверя под win найти А для чего он тебе если собрался работать с ADS 5.x под Netware ACE 5.x у тебя есть , Remote ADS for Netware тоже vladru пишет: всё-же скажите пожалуйста нубо- новеллу как мне к ADS-Novell подключаться Да как больше нравится. Коннект проверить можно с помощью AdsIsServerLoaded(смотри синтаксис) ну а далее базы юзать через dbusearea с соответствующим RDD (или USE с соответствующим RDD).....как больше нравится. ЗЫ А вообще с Netware надо уходить коли он староват и работает только по IPX , так как если на станции будет стоять что то выше чем VISTA то прицепиться к ADS Netware не получится так как начиная с VISTA протокол IPX не поддерживается

vladru: Dima пишет: А для чего он тебе если собрался работать с ADS 5.x под Netware ACE 5.x у тебя есть , Remote ADS for Netware тоже Не очень понял что такое Remote ADS for Netware Вообще у меня такая ситуация: у заказчика Clipper+ADS-Netware. Он хочет перейти на Harbour+ADS (т.к они вынуждены использовать win-XP), может потом и с NetWare уйдет... Но работаю я НЕ на его сервере, а дома, где у меня NetWare нет. Заказчику отправляю переделанные модули для проверки. Неудобно конечно, но пока так... Вот и получается что у меня должна быть возможность скомпилировать код дома (под win-7) так чтобы он у заказчика (под XP+ADS-NetWare) работал. Может подскажите организационную схему такой работы ?

Dima: vladru пишет: Может подскажите организационную схему такой работы ? у меня для таких целей дома стоит сервер Netware иначе кодить придется в слепую. по ходу своих клиентов я уже перевел под ADS Windows так что сервак стоит без дела и продается ЗЫ Хотя можно попробовать у себя включив в проге Local ADS а отправляя заказчику переделывать в Remote ADS , это всего одна строка в проге.

Dima: vladru пишет: Не очень понял что такое Remote ADS for Netware Я имел в виду ADS for Netware и установка в программе должна быть SET SERVER REMOTE или же AdsSetServerType(2) ЗЫ #command SET SERVER REMOTE => AdsSetServerType( ADS_REMOTE_SERVER )

vladru: Dima пишет: Хотя можно попробовать у себя включив в проге Local ADS а отправляя заказчику переделывать в Remote ADS , это всего одна строка в проге. Угу, и тогда дома нужно иметь две версии harbour, - одну для ace-win-ADS-9.1 чтобы компилировать для проверки у себя - другую для ace5.5. чтобы компилировать для отправки заказчику ? Так (я не уверен что всё верно понимаю) ?

Dima: да нет иметь надо только одну RDDADS для версии ADS 5.5 которая в свою очередь может работать с Local сервером дома а у заказчика с Remote сервером ADS Netware

vladru: Dima пишет: надо только одну RDDADS для версии ADS 5.5 которая в свою очередь может работать с Local сервером дома Т.е. RDDADS для версии ADS 5.5 будет работать с моим локальным ADS сервером версии 9.1 ?

Dima: vladru пишет: Т.е. RDDADS для версии ADS 5.5 будет работать с моим локальным ADS сервером версии 9.1 ? Нет. С версией 5.5 9.1 вам зачем я не пойму ?

vladru: Dima пишет: 9.1 вам зачем я не пойму ? Дык, а где мне дома взять локальный сервер версии 5.5, да еще под win?

Dima: vladru пишет: Дык, а где мне дома взять локальный сервер версии 5.5 Он уже есть в составе ACE линк на который я давал (adsloc32.dll) ace.h я забыл вот http://gfile.ru/a2eNn

nick_mi: Ну вообще-то версия RDD для 5.5 и соответствующий ACE32.DLL должен работать с сервером 9.9. По крайней мере, я когда-то пробовал на 10 версии для WIN, и у меня работало, и CLIPPER в том числе. Клиент более низкой версии допускает работу с сервером более высокой версии. Наоборот только работать не будет.

vladru: Понял. -Значит крушу свой ADS 9.1 - он уже нафиг не нужен; -кладу в папку с прогой Ваш архив -в программе делаю SET SERVER LOCAL (если у себя запускаю) (тогда программа будет делать серверные вызовы через DLL из папки программы) Осталось только RDDADS пересобрать под присланный Вами acesdk5.5. (И всё-же где написано как это сделать не пересобирая весь Harbour ?)

Dima: vladru Лезем в папку harbour\contrib\rddads\ Там создаем батник (даю свой вариант....правьте) [pre2] set PATH=C:\MinGW\bin set HB_INSTALL_PREFIX=c:\hb32mingw set HB_DIR_ADS=C:\ads.10.10\acesdk set HB_WITH_ADS=C:\ads.10.10\acesdk c:\hb32mingw\bin\hbmk2 rddads.hbp [/pre2] После правки запускаем его и должен собраться RddAds

vladru: У заказчика оказывается ADS 7.1 под Novell. Меня чего-то сглючило на 5.X. - Я скачал acesdk 7.1. с сайта http://devzone.advantagedatabase.com/ - пересобрал rddads с ним как указал Dima Заказчик запускает у себя на машине где стоит ADS Novell такой скрипт: #include "ads.ch" proc main REQUEST ADS rddSetDefault("ADSCDX") SET SERVER REMOTE ? AdsConnect("Z:") // .F. ? AdsConnect("z:") // .F. ? AdsConnect("\\Server") // .F. return Результат удручает - к ADS серверу не подключается. Что может быть не так?

Dima: а если добавить rddRegister("ADS",1) AdsRightsCheck(.F.) и юзануть AdsIsServerLoaded() Netware у него по IPX работает ? Novell Client на рабочей станции стоит ?

Dima: vladru пишет: AdsConnect("\\Server") Тут этого видимо мало будет и нужно указать том еще [pre2] Parameters pucServerName (I) Full file path of the data dictionary file, server name, or drive letter to which to connect. If the application uses a server name as the parameter, it must include the share name for Windows, path from the root for Linux, or volume name for Novell NetWare as well. For example, use "\\server\share", "\\server\path_from_root", or "\\server\volume". Linux users can also connect to the local machine using a direct path such as "/mydata". All Advantage clients and servers consider either slash type (forward or backslash) to be a path delimiter, this means you could also use a connection path with forward slashes, such as "//server/volume". Linux users should also reference the REPLACE_UNC_SERVER section in the ads.ini documentation. [/pre2] PS я когда юзал ADS по IPX из Harbour то AdsConnect вообще не использовал и пробни \harbour\contrib\rddads\tests\manage.prg только там поправить придется кое что Вместе со своим EXE давал ему еще и "ansi.chr","extend.chr","ace32.dll","axcws32.dll" ?

vladru: Dima пишет: Вместе со своим EXE давал ему еще и "ansi.chr","extend.chr","ace32.dll","axcws32.dll" ? Да, давал. я когда юзал ADS по IPX из Harbour то AdsConnect вообще не использовал Может дадите примерчик как подключались/пользовали ? Или Вы просто имеете ввиду что никаких доп.движений не делали. Только REQUEST ADS SET SERVER REMOTE а дальше работаем с базой как обычно Netware у него по IPX работает ? Novell Client на рабочей станции стоит ? Да, да. Я еще не понимаю как указать что надо IPX использовать. Вроде, из документации, ads-клиент это сам должен понять... Может каие-то dll нужны или доп.движения ? Насчет AdsIsServerLoaded: #include "ads.ch" proc main REQUEST ADS rddRegister("ADS",1) AdsRightsCheck(.F.) rddSetDefault("ADSCDX") SET SERVER REMOTE ? "AdsIsServerLoaded result:", AdsIsServerLoaded() // ответ 0 return Ну вроде 0 это как раз и хорошо? т.к. согласно ADS.HLP: AdsIsServerLoaded возвращает целое число и AE_SUCCESS как раз 0 (посмотрел в ace.h) (правда согласно тому же ADS.HLP: AdsConnect тоже должна возвращать целое, а в harbour возвращает почему-то логическое....) еще, кстати, в ADS.HLP написано AdsConnect устарела и надо использовать AdsMgConnect manage.prg - поправил/построил, но испытать на Novell уже не успел (выходные)

vladru: Dima Спасибо за Ваши ответы. Пока разобрался, но может еще будут вопросы.... На сегодня выводы такие: 1. AdsConnect использовать, наверно, не стоит т.к. она возвращает только T/F. Вместо неё есть AdsMgConnect. Она возвращает 0 или код ошибки. 2. Описание ошибки есть в ADSERROR.HLP для старых ACE или в advantage.chm для 9. Так я узнал что моя проблема была в том, что версия клиента была старше версии сервера (ошибка 6316) 3. Если есть вопросы по подключению к ADS сначала см. \contrib\rddads\tests\manage.prg

Dima: Похоже фича dborderinfo(DBOI_SKIPWILD,,,cPattern) в ADS не работает... Печалька.

Haz: вроде уже писали здесь об этом - не работает. http://clipper.borda.ru/?1-4-580-00000368-000-0-0 мож через sql запрос можно вывернуться ?

Dima: Haz пишет: мож через sql запрос можно вывернуться ? может но не знаком с ними

Haz: Dima пишет: не знаком Рекомендую, многое становиться очень просто, и к тому же с авто оптимизацией ( по возможности ) на сервере. создаешь словарь, добавляешь в него таблицы и выполняешь запрос , результатом которого будет открытая рабочая область с нужными записями из одной или нескольких таблиц сведенных в одну автоматом. PS для твоего случая в синтаксисе есть оператор LIKE cPattern

Dima: Haz пишет: PS для твоего случая в синтаксисе есть оператор LIKE cPattern Можешь примерчик показать ?

Dima: Haz Нашел инфу на форуме. Сделал вот так , но AdsCreateSQLStatement(,2) выдает .F. [pre2] proc main #include "ads.ch" local sQlStr REQUEST ADS rddSetDefault( "ADSCDX" ) REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU866 hb_cdpSelect( "RU866" ) SET SERVER LOCAL AdsSetFileType(ADS_CDX) AdsRightsCheck(.F.) use volvo exclusive new index on indeks to ttt ? AdsConnect( ".\" ) // .T. ? AdsCreateSQLStatement(,2) // .F. sQlStr:='SELECT * FROM volvo WHERE indeks Like "%44%"' ? AdsPrepareSQL(sQlStr) // .F. ? AdsExecuteSQL(sQlStr) // .F. wait return [/pre2]

Dima: Dima пишет: use volvo exclusive new index on indeks to ttt ? AdsConnect( ".\" ) // .T. ? AdsCreateSQLStatement(,2) // .F. sQlStr:='SELECT * FROM volvo WHERE indeks Like "%44%"' ? AdsPrepareSQL(sQlStr) // .F. ? AdsExecuteSQL(sQlStr) // .F. Не много переделал [pre2] select 100 ? AdsConnect( ".\" ) // .T. ? AdsCreateSQLStatement(,2) // .T. sQlStr:='SELECT * FROM volvo WHERE indeks Like "%44%"' ? AdsPrepareSQL(sQlStr) // .T. ? AdsExecuteSQL(sQlStr) // по прежнему .F. , почему ? ? AdsGetLastError() // 7200 [/pre2]

Haz: только дошел до компа. делал примерно так IF AdsCreateSqlStatement( cAlias, 3 ) // использовал ADT а не CDX - думаю не принципиально IF ADSVERIFYSQL( cSql ) AdsExecuteSqlDirect( cSql ) ELSE END позже попробую примерчик подробнее

Dima: Haz Ради теста чеканул sQlStr:="SELECT * FROM VOLVO WHERE FIRMA=7" ? ADSVERIFYSQL(sQlStr) // .F. що за на фик..........вроде ж нормальный запрос

Haz: Dima пишет: що за на фик AdsCreateSqlStatement( cAlias, 3 ) Дима, попозже ок ? полно дел по дому )

Dima: Haz OK подожду Переделал снова пример , результат нулевой [pre2] proc main #include "ads.ch" local hh local sQlStr REQUEST ADS rddSetDefault( "ADSCDX" ) REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU866 hb_cdpSelect( "RU866" ) SET SERVER LOCAL AdsSetFileType(ADS_CDX) ? AdsConnect(".\") // .t. ? hh:=AdsConnection() // 17005400 use volvo new Select 0 ? AdsCreateSQLStatement("test",2) // .t. sQlStr:="SELECT * FROM VOLVO WHERE FIRMA=7" ? ADSVERIFYSQL(sQlStr) // .f. ? AdsExecuteSqlDirect(sQlStr) // .f. ? AdsGetLastError() // 7200 ? alias(),reccount() wait return [/pre2] ЗЫ чисто ради интереса попробовал работу функций типа SP_* , работают однако [pre2] cAlias := "cursor" cSql := "EXECUTE PROCEDURE sp_mgGetInstallInfo()" ADSCreateSQLStatement( cAlias,2 ) AdsExecuteSQLDirect( cSql ) While !(cAlias)->( eof() ) * ? (cAlias)->Username, (cAlias)->Address, (cAlias)->DictionaryUser ? (calias)->Version (cAlias)->( dbSkip() ) End [/pre2]

Haz: Дима почту скинь , часов в 9 отправлю пример работающий в конфу позже выложу PS. А пока - почему может не работать 1. Нужно создать словарь ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO" ) 2 создать пользователя AdsDDCreateUser(, "Guest", "" , "Пользователь Guest" ) 3 пихнуть в словарь базу AdsDDaddTable( "AdsDemoAT", "AdsDemoAT.dbf", "" ) 4 не использовать в запросе двойную ковычку " а только ' cSql := "SELECT * FROM AdsDemoAT WHERE LAST Like '%m%'" 5 цепляться к словарю adsConnect60( cDictionary, 0, "ADSSYS", '', 7, @hConnection ) и только потом запрос SQL

Dima: Да оно и без словаря работает. Вот в этой теме я смотрел примеры , там словарем и не пахнет http://clipper.borda.ru/?1-4-0-00000430-000-10001-0-1251195209

Haz: Dima пишет: ЗЫ почта улетело, в конфу позже

Dima: да получил , спасибо ! я полагал что и без словаря все должно работать...... ушел думать.

Dima: Haz я пожалуй выложу пример. [pre2] proc main #include "ads.ch" local sQlStr local cpath:=hb_CurDrive()+":\"+CurDir()+"\" local cDictionary:=cpath+"temp.add" REQUEST ADS rddSetDefault( "ADSCDX" ) REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU866 hb_cdpSelect( "RU866" ) SET SERVER LOCAL AdsSetFileType(ADS_CDX) if !AdsConnect(cpath) ? "Не могу подключится к ADS" quit endif use VOLVO shared new // можно не открывать но у меня в задаче эта база открыта if !file(cDictionary) ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO" ) endif IF adsConnect60( cDictionary, 0, "ADSSYS", '', 7, ) * AdsDDCreateUser(, "Guest", "" , "Пользователь Guest" ) // и без нее работает AdsDDaddTable( "volvoAT", cpath+"volvo.dbf", "" ) ELSE ? "Ошибка подключения к словарю данных " ENDIF Select 0 AdsCreateSQLStatement(,2) sQlStr:="SELECT * FROM volvoAT WHERE indeks Like '%.44.07%'" ADSVERIFYSQL(sQlStr) AdsExecuteSqlDirect(sQlStr) ? alias(),reccount(),fcount() wait browse() return [/pre2] А как запросом получить и выбранные номера записей из базы VOLVO ?

Haz: Dima пишет: я пожалуй выложу пример. в случае с SQL вот это можно не писать if !AdsConnect(cpath) ? "Не могу подключится к ADS" quit endif т.к. подключаемся через словарь и путь есть в пути словаря use VOLVO shared new // можно не открывать но у меня в задаче эта база открыта открывать таблицу не надо вообще , сам долго не мог к этому привыкнуть ))) таблица - это то из чего делаем выборку и к ней доступ в SQL по имени и через словарь ( если таких словарей несколько ) а рабочая область получается в результате запроса - называется курсором , в зависимости от типа может быть редактируемой или толькочтение. Следовательно SHARED - тоже лишнее ( через сервер адс курсор и так всегда будет в режиме шары ) Если записывать значения в таблицу через UPDATE Volvo SET indeks = 100 то и Rlock() не требуется ( сервер сам все делает ) Если через (cAlias)->indeks := 100 - тогда Rlock() нужен Если коротко - то есть таблица и есть курсоры с нее , меняя значение в курсоре ( в раб области ) - меняем таблицу , или напрямую меняем таблицу без создания курсора ))) AdsDDCreateUser(, "Guest", "" , "Пользователь Guest" ) // и без нее работает работает потому что в примере использовал системного пользователя ADSSYS - у него права админа а так словарю можно нарезать пользователей и дать им разные права на таблицы , разные пароли на вход и т.д. Dima пишет: А как запросом получить и выбранные номера записей из базы VOLVO ? в адс через запрос есть только ROWID , Recno() через запрос вроде не получить. я в таблицах использую поле ID типа autoinc ( нагляднее чем ROWID ). А зачем список номеров записей нужен , уверен есть варианты запроса через ROWID PS. Если работать со словарями - оч. рекомендую поставить бесплатную Advantage Architect для управления базами

Dima: Haz пишет: А зачем список номеров записей нужен например если в выборке я нашел нужную мне запись и нажав на ней ВВОД оказался бы на нужной записи в базе VOLVO что то типа VOLVO->(dbgoto(ADSSQL->recs RECNO() из VOLVO))

Haz: Dima пишет: что то типа VOLVO->(dbgoto(ADSSQL->recs RECNO() из VOLVO)) так сработает - т.к. в курсоре есть RECNO() я в данном случае использую динамический поиск - т.е. перестраиваю курсор самой базы ( в твоем случае VOLVO ) под условие нужного SQL или через ADSSetFilter - тоже быстро

Dima: Haz пишет: так сработает - т.к. в курсоре есть RECNO() Да но это RECNO() не то. Допустим в результате SQL выборки попали 2 записи с RECNO() 5677 и 10000999 (из базы VOLVO). Как мне узнать эти RECNO в самой выборке ? Вот бы как то в выборку вставить колонку в которой будет RECNO() из базы VOLVO. В теории мне только эта колонка и нужна так как дальше я смогу по этой выборке ходить связав ее по RELATION c базой VOLVO

Dima: Haz пишет: или через ADSSetFilter - тоже быстро То же им пользуюсь но нужно в уже существующем фильтре выбрать вхождения строк в названия к примеру и это работает не так быстро как с SQL запросом

Haz: Recno в случае редактируемого покажет номер физической записи из таблицы , курсор - это как фильтр по таблице и в курсоре и в таблице Recno будет совпадать

Dima: не совпадают проверял так AdsExecuteSqlDirect(sQlStr) ? volvo->(recno()),ADSSQL->(recno()) // 1,1 adssql->(dbskip()) ? volvo->(recno()),ADSSQL->(recno()) // 1,2

Haz: Haz пишет: Вот бы как то в выборку вставить колонку в которой будет RECNO() из базы VOLVO. только изменить структуру базы , добавив везде поле ID тип Integer ( Autoinc нет в CDX )а в подчиненную еще и ID_MASTER тип Integer ( перекроить структуру и перезаполнить ID можно теми же запросами через ARC32.EXE )

Haz: Haz пишет: ? volvo->(recno()),ADSSQL->(recno()) // 1,1 adssql->(dbskip()) ? volvo->(recno()),ADSSQL->(recno()) // 1,2 так ты в вольво стоишь на месте а адсскуль - скипанул на единицу попробуй через запрос найти любую уникальную запись вольво и сравни recno по ней

Dima: я не про то ;) у ADSSQL свои recno() а в VOLVO свои. И мне нужно сидя в бровсе в ADSSQL при выходе из него оказаться на такой же записи как и в базе ADSSQL. То есть сидел я выборке на коде товара OC2187E-ERT то после выхода должен оказаться в базе VOLVO тоже на коде OC2187E-ERT

Haz: Dima пишет: у ADSSQL свои recno() а в VOLVO свои. ТОЧНО (((( тогда через ID или можно через ROWID попробовать через ROWID можно, но эта псевдоколонка должна быть определена явно , причем адс уверяет что это выход ))) End users and application developers can use rowids for several important functions: · Rowids are the fastest means of accessing particular rows. · Rowids can be used to see how a table is organized. · Rowids are unique identifiers for rows in a given table. В качестве минуса - нельзя строить запрос SELECT * , нужно с перечислением полей This pseudocolumn is not evident when listing the structure of a table by executing a SELECT * FROM . . . statement. However, each row's address can be retrieved with an SQL query using the reserved keyword ROWID as a column name, for example: второй минус RECNO() сначала придется поймать фильтром , а только потом GoTO ((((

Dima: почитал help DBDBDBTABTABBrXAAN The first six characters of the ROWID represent the database ID. It is based on the connection path. The next six characters of the ROWID represent the table ID. If the table is a database table, that is, a table that belongs to an Advantage Data Dictionary, the table ID represents the object ID of the table in the data dictionary. If the table does not belong to an Advantage Data Dictionary, the table ID is constructed using the name of the table file. The last six characters represent the record number of the row in the table. Получается что BrXAAN RECNO() из базы VOLVO , но как его к цифре привести не понял Как то так но это не все......... hb_base64Decode(right(rowid,6)) нужна функция что в целое переведет

Haz: Dima пишет: но как его к цифре Вот тут говорят с версии 11 уже есть функция , а для версий ниже предлагается самописная ((( - я ее расшифровать не смог ((( http://devzone.advantagedatabase.com/forum/questions/3311/select-record-by-rowid

Dima: Haz пишет: а для версий ниже предлагается самописная Спасибо. Но не понял как ее конвертнуть в Habrour

Haz: Dima пишет: Но не понял как ее конвертнуть в Habrour аналогично хотя можно порыть тут the last 6 chars of a rowid is the physical recno in base64 code.

Dima: Haz пишет: хотя можно порыть тут the last 6 chars of a rowid is the physical recno in base64 code. Писал выше что пробовал hb_base64Decode(right(rowid,6)) , но это не то так как на выходе получаем далеко не цифры

Haz: После Decode64 скорее всего получим cBinary который нужно скормить еще какой нить BIN2I() ... будут цифры но опять не те ((((

Dima: кормил всем BIN2* все мимо

Haz: Вот сюда корми FUNCTION Decode64(cCode) **************************************************************************** STATIC cString := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" LOCAL nStevec LOCAL nReturn := 0 LOCAL nLen := Len(cCode) IF Empty(cCode) .OR. Valtype(cCode)=='U' ; RETURN 0 ; ENDIF FOR nStevec := 1 TO nLen nReturn := nReturn*64 + (At(Substr(cCode, nStevec,1), cString)-1) NEXT RETURN nReturn Взято тут http://nntp-archive.sybase.com/nntp-archive/action/article/%3C4550525e@solutions.advantagedatabase.com%3E

Dima: а вот это прям в десятку

Dima: красота и relation по recno() пашет set relation to Decode64(right(ADSSQL->rowid,6)) into volvo есть 2 вопроса 1. Если у меня база VOLVO все же открыта и в ней открыты индексы то SQL запрос будет выполнятся быстрее или ему индексы не нужны ? Серверный фильтр если находит подходящий индекс под условие фильтра то ставится мгновенно. 2. SQL запрос в зависимости от условия может ставится некоторое время. Можно ли какой то индикатор повесить что бы юзер видел что прога не висит. База 5 лимонов записей и SQL запрос может быть не простым.

Haz: Dima пишет: есть 2 вопроса 1 при построении SQL во всю используются индексы, ADS рекомендует их использовать для увеличения скорости. 2 на счет индикатора не в курсе , когдато давно вроде видел ... но не уверен Время зависти от наличия нужных индексов , 5 лимонов это максимум пара секунд если структура баз правильная. Вообще ADS в этом плане - очень шустрый

Dima: Понял. Спасибо. Пробнул юзануть вот так но ни че не кажет индикатор AdsRegCallback( {| nPercent |outputstuff( nPercent,xxyy) } ) AdsExecuteSqlDirect(sQlStr) AdsClrCallback() где xxyy lastrec() из VOLVO Придется вешать лейбу - выполняется SQL запрос

Dima: Еще вопросец. Как из SQL выборки удалить ряд записей ?

Haz: Dima пишет: Как из SQL выборки удалить ряд записей или фильтром или физически и из таблицы тоже фильтром можно так добавить виртуальное поле , установить его в true и фильтровать по нему. в не нужных это поле скинуть в false и фильтр их скроет вот пример запроса - виртуальное поле s по умолчанию выставлено в true select true as s, adsdemoat.* from adsdemoat

Dima: Haz

Dima: Последний вопрос на сегодня ;) если ручками набирать запрос то он выглядит так SELECT ROWID,indeks FROM volvoAT WHERE indeks Like '%LM%' А если использовать переменную в операторе LIKE то как правильно написать ? Скажем CC:="LM" , как этот СС туда правильно вставить ? Что то не пашет у меня. Разобрался ! CC:="LM" SQLSTR:="SELECT ROWID,indeks FROM volvoAT WHERE indeks Like "+"'"+'%'+CC+'%'+"'"

Dima: Haz пишет: фильтром можно так добавить виртуальное поле , установить его в true и фильтровать по нему. имеется в виду какой фильтр , серверный , обычный или есть какой то SQL-ий ? Haz пишет: в не нужных это поле скинуть в false и фильтр их скроет ADS пишет что таблица только для чтения при попытке записи в поле S На DBdelete() та же реакция естественно. ЗЫ Извини что напрягаю ;)

Haz: Dima пишет: Извини что напрягаю да ерунда, пока дома сижу Dima пишет: только для чтения точно не учел ((( в данном случае таблица только чтение можно использовать тот же RowID с перестроением SQL по типу select rowid, adsdemoat.* from adsdemoat where rowid not in ('B8vqUvAAAAAEAAAAAB', 'B8vqUvAAAAAEAAAAAC') где B8vqUvAAAAAEAAAAAB и B8vqUvAAAAAEAAAAAС rowId которые надо скрыть построив sql алиас ADSSQL можно пересоздать а Browse:RefreshAll по идее должно сработать не проверял (( или AdsSetAof по RowId делать PS т.к. добавили псевдостолбец - курсор будет опять ридонли еще вариант - создать массив из номеров Recno которые нужно спрятать и фильтровать по нему - тогда курсор будет редактируемый ЗЫ ушел гулять с ребенком )

Dima: На ночь глядя вопрос возник ;) Я смотрел твой пример и тот что есть в CONTRIB\RDDADS и какое то время проводил эксперименты. Пришел к выводу что перед тем как сделать SQL запрос нужно сделать вот так. [pre2] use VOLVO shared new // можно не открывать но у меня в задаче эта база открыта hh:=nil if !hb_FileExists(cDictionary) // для каждого юзера создаем свой словарик ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO" ) AdsDDaddTable( "volvoAT", cpath+"volvo.dbf", "" ) AdsDDCreateUser(, "Guest", "" , "Пользователь Guest" ) *adsConnection() // похоже это не нужно *AdsDisconnect() // похоже это не нужно endif IF !adsConnect60( cDictionary, 0, "Guest", '', 7,@hh ) ? "Ошибка подключения к словарю данных " ENDIF Эта конструкция работает , или я в чем то не прав ?! [/pre2]

Haz: Dima пишет: *adsConnection() // похоже это не нужно *AdsDisconnect() // похоже это не нужно в данном случае не надо и все работает, это кусок из моего кода где сначала логинюсь к словарю с админскими, создаю базы и индексы , а потом дисконнект и далее коннест под простым юзером

Dima: Haz пишет: PS т.к. добавили псевдостолбец - курсор будет опять ридонли даже без добавления оного она все равно READ ONLY. Все виды выборок у меня укладываются в одну строку , кроме одной. В которой нужно по коду товара выбрать остатки из другой базы и показывать только то что есть в остатке. То есть по сути убрать (отфильтровать) не нужные записи а оно во как READ ONLY и USER функцию мою я так понимаю SQL запрос не поймет. Идейка пришла. Я ведь могу сделать COPY TO с условием FOR во временную MEM: базу и уже по ней ходить. Ан нет в MEM: базу не получится , тормознул . Можно просто выбрать из запроса нужные записи и метнуть их в MEM: базу и по ней ходить.

Haz: может быть readonly потому что таблица по которой делаешь запрос уже расшарена и открыть ? Dima пишет: могу сделать COPY TO лучше сразу в SQL прописать SELECT * INTO #TmpBase FROM ... WHERE ... создасться временная ( в памяти если указан знак # и на диске если напишем просто TempBase без # ) таблица TmpBase и по ней можно тоже выполнять запрос SELECT * FROM #TempBase ... Примерно так cSql := 'SELECT Client_Code INTO #CLIENTS FROM Orders GROUP BY Client_Code' SQL(, cSql ) // моя функция , если алиас не указан , используется "TMP" , а после выполнения TMP->(DbcloseArea()) cSql := 'SELECT Client_Code FROM #CLIENTS' SQL( 'SQL_CLIENTS', cSql ) Потом, когда база не нужна ее нужно убить cSql := "DROP TABLE #CLIENTS" SQL(,cSql)

Dima: Haz пишет: INTO #TmpBase совсем другое дело ее корректировать можно

Haz: Вообще при использовании SQL я перестал использовать USE cBase SHARED и тд сами таблицы закидываю в словарь, а работаю с ними только через курсоры, без прямого открытия через USE. Все редактируется и удаляется тоже в курсорах. Индексы создаю по всем полям по которым будет выборка и почти не использую Dbseek(). Обленился , вся оптимизация в мозгах у сервера а не в моей голове ) Добавлю еще : в больших по числу записей таблицах стараюсь на держать строки а только ID на строку в справочнике т.к. всегда могу склеить для показа запросом, зато скорости выборки фантастические

Dima: Haz пишет: Вообще при использовании SQL я перестал использовать USE cBase SHARED и тд у меня все наоборот ;)

Haz: Dima пишет: у меня все наоборот ;) сам лет десять делал наоборот )))) пока не появилась задача клеить на лету из 10 баз одну добило сравнение кода на clipper/harbour против одной строки запроса

Dima: Haz пишет: лучше сразу в SQL прописать SELECT * INTO #TmpBase FROM ... WHERE ... а закрывать ее как обычно ? adssql->(dbclosearea()) AdsDisconnect( hh )

Haz: рабочая область закрывается через dbclosearea() AdsDisconnect - перед выходом из программы и то без него сервер обнаружит висяк и обрубит сам

Haz: вот мой вызов SQL FUNCTION SQL( cAlias, cSql, lLog ) LOCAL cTempAlias := '_TMP' + NToC( SECONDS() ) LOCAL lClose := FALSE LOCAL nSaveArea := Select() LOCAL i := 0 LOCAL nLog := 0 LOCAL cBuffer := '' IF lLog == NIL lLog := .F. END IF cAlias == NIL cAlias := cTempAlias lClose := .T. END IF lLog IF !File(DirPrg() + "\LogSql.Log") nLog := FCreate( DirPrg() + "\LogSql.Log" ) ELSE nLog := FOpen( DirPrg() + "\LogSql.Log", 66 ) END FSeek( nLog, 0, 2 ) cBuffer := DToC(Date()) + " " + Time() + " " + ProcName(1) + "()" + " -> " + cSql + CRLF FWrite( nLog, cBuffer, Len( cBuffer )) FClose(nLog) END IF (cAlias)->(USED()) ( cAlias ) ->( DBCLOSEAREA() ) END Select( 0 ) IF AdsCreateSqlStatement( cAlias, 3 ) IF ADSVERIFYSQL( cSql ) AdsExecuteSqlDirect( cSql ) ELSE IF MsgYesNo('Error in SQL statement' + CRLF+ cSql + CRLF + ; ' function = ' + ProcName(0) + " -> line = " + NTOC(ProcLine(0)) + CRLF + ; ' function = ' + ProcName(1) + " -> line = " + NTOC(ProcLine(1)) + CRLF + ; ' function = ' + ProcName(2) + " -> line = " + NTOC(ProcLine(2)) + CRLF + ; ' function = ' + ProcName(3) + " -> line = " + NTOC(ProcLine(3)) + CRLF + ; 'Закончить работу ?') MemoWrit( "_ERRSql.txt", cSql ) QUIT END END END IF lClose ( cAlias ) ->( DBCLOSEAREA() ) DBSELECTAREA( nSaveArea ) ELSE i := ASCAN( aSqlQuery, { | q | q[ 1 ] == UPPER(cAlias) } ) IF i == 0 AADD( aSqlQuery, { UPPER(cAlias), cSql } ) ELSE aSqlQuery[ i, 2 ] := cSql END END RETURN AdsGetLastError()

Dima: Haz пишет: AdsDisconnect - перед выходом из программы и то без него сервер обнаружит висяк и обрубит сам Нет ты не прав. Я же писал что работаю по старинке через USE и только в одном месте пока хочу устроить SQL выборку. А по сему основной хендл будет hh1:=AdsConnection() А коннект с запросом имеет свой hh adsConnect60( cDictionary, 0, "Guest", '', 7,@hh ) Это я проверил хендлы разные. Поэтому конструкция adssql->(dbclosearea()) AdsDisconnect( hh ) к висяку не приведет , проверил. Вопрос в том убьется ли в памяти база #TmpBase ? Haz пишет: Добавлю еще : в больших по числу записей таблицах стараюсь на держать строки а только ID на строку в справочнике т.к. всегда могу склеить для показа запросом, зато скорости выборки фантастические Да скорость очень даже

Haz: я имел ввиду что disconnect можно не делать . а временную таблицу ( не алиас ) нужно закрывать через "DROP TABLE #TempBase"

Dima: Haz пишет: "DROP TABLE #TempBase" вот что выходит sele adssql browse() sQlStr:="DROP TABLE #TmpBase" ? ADSVERIFYSQL(sQlStr) // .f. ? AdsExecuteSqlDirect(sQlStr) // .f. error 5109

Haz: Dima пишет: error 5109 пишет что курсор по этой таблице еще открыт

Dima: да я это читал , и не понял как же корректно убить в памяти таблицу #TmpBase или достаточно ADSSQL->(dbclosearea()) ?

Dima: Dima пишет: sele adssql browse() sQlStr:="DROP TABLE #TmpBase" ? ADSVERIFYSQL(sQlStr) // .f. ? AdsExecuteSqlDirect(sQlStr) // .f. если сделать так browse() adssql->(dbclosearea()) sQlStr:="DROP TABLE #TmpBase" ? ADSVERIFYSQL(sQlStr) // ФАЙЛ НЕ ОТКРЫТ ? AdsExecuteSqlDirect(sQlStr) // .f.

Haz: Dima пишет: или достаточно ADSSQL->(dbclosearea()) ? так только область закроется , а таблица останется жить в памяти надо и то и то сначала области позакрывать все из этой таблицы, а потом DROP саму временную таблицу

Haz: если сделать так browse() adssql->(dbclosearea()) sQlStr:="DROP TABLE #TmpBase" ? ADSVERIFYSQL(sQlStr) // ФАЙЛ НЕ ОТКРЫТ ? AdsExecuteSqlDirect(sQlStr) // .f. ` это должно работать правильно , из #TmpBase толко один SELECT ? и где AdsCreateSqlStatement() для запроса нужно все 3 вызова AdsCreateSqlStatement( cAlias, 2 ) ADSVERIFYSQL( cSql ) AdsExecuteSqlDirect( cSql )

Dima: Haz пишет: это должно работать правильно , из #TmpBase толко один SELECT ? ну да вроде. у меня открыто 2 базы , VOLVO через USE и выборка SQL c алиасом ADSSQL

Haz: для запроса нужно все 3 вызова AdsCreateSqlStatement( cAlias, 2 ) ADSVERIFYSQL( cSql ) AdsExecuteSqlDirect( cSql )

Dima: Haz пишет: и где AdsCreateSqlStatement( точно ! не доглядел , работает

Dima: насчет ROWID ты был прав , таблица становится READ ONLY , даже если юзать INTO #TmpBase

Haz: Dima пишет: насчет ROWID добавь поле ID - Integer и при DbAppend() что нибудь типа NewID() FUNC NewID() LOCAL nID := 0 SQL('GetID', 'SELECT TOP 1 ID FROM VolvoAT ORDER BY ID DESC') nId := GetID->ID GetID->(DbClosArea()) RETURN nId + 1 И далее пользуй ID а не Recno() ROWID думаю тоже можно поправить - определять его в образующем SELECT ROWID AS R, VaolvoAt.* INTO # тогда в темпбазу он должен перейти полем R.... ходя не проверял ( проверил - редактируется

Dima: Haz пишет: ROWID думаю тоже можно поправить - определять его в образующем SELECT ROWID AS R, VaolvoAt.* INTO # тогда в темпбазу он должен перейти полем R.... ходя не проверял ( проверил - редактируется Cамое то

Dima: что то косяк вылазит. все вроде норм проходит а ошибка есть sQlStr:="SELECT ROWID AS Recs , INDEKS INTO #TmpBase FROM volvoAT WHERE MARKA=1 and naim like '%B%'" ? dosql(sQlStr) //0 sele adssql set relation to Decode64(right(recs,6)) into volvo browse() sQlStr:="DROP TABLE #TmpBase" set relation to adssql->(dbclosearea()) ? AdsCreateSQLStatement(,2) // .t. ? ADSVERIFYSQL(sQlStr) // .t. ? AdsExecuteSqlDirect(sQlStr) //.t. ? AdsGetLastError() // 5018 к чему бы это и что я сделал не так ?

Haz: MARKA=1 По MARKA надеюсь индекс есть для оптимизации))) 5018 эта и у меня постоянно вылазит , забил

Dima: Haz пишет: забил

Haz: вижу все заработало , поздравляю

Dima: Haz Спасибо без тебя не разобрался бы !

Dima: Планирую еще сложные отчеты переделать , чую SQL тут должен помочь Точнее выборку для них.

Haz: Dima пишет: не разобрался бы разобрался бы , если б захотел и не бросил )) Планирую еще сложные отчеты переделать установи Advantage Database Architect - помогает ошибки в запросах ловить

Dima: Haz пишет: установи Advantage Database Architect Стоит давно уже. Haz пишет: разобрался бы , если б захотел и не бросил )) на это ушло бы очень много времени

Dima: Haz Есть вопросик. Собственно вот так я выбираю остатки товара на дату. Пример не самодостаточный но вполне понятен. А вот как такую же выборку в базу VREM сделать с помощью SQL запроса ? [pre2] sele nomen do while !eof() f_nomer:=nomen->nomer sele karta ost:=0 if dbseek(f_nomer) karta->(dbOrderInfo(DBOI_SCOPEBOTTOM,,,f_nomer)) do while !eof() if karta->data_z>dth2 skip loop endif ost+=(karta->prixod-karta->rasxod) skip enddo karta->(dbOrderInfo(DBOI_SCOPEBOTTOMCLEAR)) VREM->(dbappend()) repl VREM->ostat with ost,; VREM->cod with nomen->cod,; VREM->naim with nomen->naim endif sele nomen skip enddo [/pre2]

Haz: Dima пишет: А вот как примерно так do !nomen->(eof()) cSql := "select SUM( prixod - rasxod ) AS ost from karta where data_z <= dth2 and nomer = '" + nomen->nomer + "'" SQL( cAlias, cSql) If !(cAlias)->(Eof()) VREM->(dbappend()) VREM->ostat := cAlias->ost VREM->cod := nomen->cod VREM->naim := nomen->naim END cAlias->(DbCloseArea()) nomen->(DbSkip(1)) end где nomer - имя поля по которому SCOPE ( из примера на ясно как звать ) можно подумать как вообще обойтись одним запросом базы большие ? мож на мыло прислать ?

Dima: Haz пишет: где nomer - имя поля по которому SCOPE ( из примера на ясно как звать ) Это уникальный номер складской карточки. Думаешь с таким запросом быстрее будет работать нежели по старинке ?

Haz: Dima пишет: базы большие ? мож на мыло прислать ?

Dima: Да вышлю чуть позже.

Dima: Отправил

Haz: Dima пишет: можно подумать как вообще обойтись одним запросом где то так SELECT N.NOMER, N.COD, N.NAIM, O.OST FROM NOMEN N LEFT JOIN ( SELECT SUM (K.PRIXOD -K.RASXOD) AS OST, K.NOMER FROM KARTA K WHERE K.DATA_Z <= KDTH2 GROUP BY K.NOMER ) O ON N.NOMER = O.NOMER сейчас по твоей базке погоняю

Haz: вот результат SELECT N.NOMER, N.COD, N.NAIM, O.OST FROM NOMEN N LEFT JOIN ( SELECT SUM (K.PRIXOD - K.RASXOD) AS OST, K.NOMER FROM KARTA K WHERE K.DATA_Z <= '01.01.2013' GROUP BY K.NOMER ) O ON N.NOMER = O.NOMER обязательны индексы по NOMER DATA_Z PS: если таблицы конвертнуть в родной для ADS формат .ADT - запрос выполняется почти в два раза быстрее

Dima: Сколько примерно по времени формировалась такая выборка на 01.01.2013 ?

Dima: Dima пишет: sQlStr:="SELECT ROWID AS Recs , INDEKS INTO #TmpBase FROM volvoAT WHERE MARKA=1 and naim like '%B%'" Haz А каким образом я могу устроить SEEK по этой базе #TmpBase. Как то можно создать такой же временный индекс в памяти ?

Haz: 10 сек на старом компе с XP

Haz: Haz пишет: А каким образом я могу устроить SEEK по этой базе #TmpBase. Как то можно создать такой же временный индекс в памяти ? временный не пользовал а постоянный как то так cSql := "EXECUTE PROCEDURE sp_CreateIndex90( '" + cBase + "','" + cBase + ".cdx','" + cField + "','" + cField + "', '', 2, 512, '' )" а что искать то в ней надо ?

Dima: Haz пишет: а что искать то в ней надо ? Нужно переходить к определенному ROWID в некоторых случаях Haz пишет: EXECUTE PROCEDURE sp_CreateIndex90 Спасибо ! Haz пишет: 10 сек на старом компе с XP Круто

Dima: функции обратной DECODE64 не встречал ? Типа ENCODE64

Haz: Dima пишет: Нужно переходить к определенному ROWID в некоторых случаях мож AdsSetAof() использовать ? темпбаза же не большая

Dima: Haz пишет: мож AdsSetAof() использовать ? неа , это ж фильтр а надо именно перейти к записи.

Haz: Dima пишет: функции обратной DECODE64 не встречал ? Типа ENCODE64 талько если самому писать , за основу взять харборную hb_Encode ...

Haz: Haz пишет: неа , это ж фильтр а надо именно перейти к записи. nRecSave := Recno() nRec := 0 AdsSetAOF() DbGotop() IF !Eof() nRec := RECNO() END AdsClearAof() DbGoto( IF( nRec <> 0. nRec, nRecSave ) или вообще по __DbLocate()

Dima: Haz пишет: или вообще по __DbLocate() а это возможно сделать SQL запросом ?

Haz: Dima пишет: а это возможно сделать SQL запросом конечно , только запрос - почти тот же фильтр самое простое - (cAlias)->( __dbLocate( bBlock,,,,.F.))

Dima: Haz пишет: (cAlias)->( __dbLocate( bBlock,,,,.F.)) Буду тестить , спасибо !

Dima: Добрался наконец и начал переделывать живую задачу под REMOTE ADS И сразу попал на грабли cDictionary:=diskads+"sql\"+sys_name+"f12" словарь не создается почему то совсем ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO" ) cDictionary -> \\127.0.0.1\sklad$\sql\supervisorF12 лупит ошибку 6420

Haz: AdsConnect цепляется к серверу ? путь к словарю правильный ? создай словарь руками при помощи ARC32 и им же базы в него подабавляй 127.0.0.1 - этож на локальной машине , пропиши обычный путь

Dima: Haz пишет: AdsConnect цепляется к серверу ? Конечно. Рабочая задача. Haz пишет: путь к словарю правильный ? Да Haz пишет: создай словарь руками при помощи ARC32 и им же базы в него подабавляй Не вариант так как нужно делать это прям из проги. Haz пишет: 127.0.0.1 - этож на локальной машине , пропиши обычный путь Все верно так как работаю дома с REMOTE или LOCAL ADS именно через 127.0.0.1 (комп то один)

Dima: сложил в папку diskads+"sql\" файлик test.prg и проверил HB_fileexists(diskads+"sql\test.prg") , все норм .T. путь к файлу получился таким \\127.0.0.1\sklad$\sql\test.prg ЗЫ Это у клиента мы уже меняем IP на сетевой что то типа 192.168.0.100 а дома всегда юзал 127.0.0.1 sklad$ - это имя расшаренного скрытого ресурса net share покажет sklad$ c:\works\alex\ads_sklad Dima пишет: ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO" ) Перед этой функцией вставил c:=fcreate(cDictionary+".test") fclose(c) файл нормально создался Такое впечатление что ADSDDCREATE не работает с полным путем UNC

Haz: Dima пишет: Такое впечатление что ADSDDCREATE не работает с полным путем UNC вполне возможно что так , но при REMOTE попробуй через LOCAL ( замени 7 на 1 в строке конекта )

Dima: Haz пишет: попробуй через LOCAL до adsConnect60 я еще не дошел и создаю словарь до этого. C Local пробовал тот же эффект собственно код [pre2] if !file(cDictionary) // для каждого юзера создаем свой словарик ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO") // вот тут получаю 6420 и ADSDDCREATE вернул .F. AdsDDaddTable( "volvoAT",PFL+"volvo.dbf", "" ) AdsDDCreateUser(, alltrim(sys_name), "" , "Пользователь "+alltrim(sys_name)) endif IF !adsConnect60( cDictionary, 0, alltrim(sys_name), '', 7,@tmphh ) Soob("Ошибка подключения к словарю данных","r/r","gr+/r") return nil ENDIF [/pre2]

Haz: может с $ пути не понимает ???? надо эксперементировать выведи путь в INI дома руками обычный впиши а у клиента UNC

Haz: вроде не понимает IP в строке пути , если заменить на имя компа - работает

Dima: да UNC путь не понимает зараза. положил чистую ADD и пробнул подрубится через adsConnect60 , не фига. если путь обычный типа c:\бла бла то работает странно все это

Haz: Dima пишет: да UNC путь понимает путь вида \\сервер\шара

Dima: странно у меня не понял cDictionary:="\\dima-21a4fe250e\sklad$\"+"sql\"+"temp.add" tmphh:=nil ? adsConnect60( cDictionary, 0, "ADSSYS", '', 7,@tmphh ) //.f. хотя в проводнике дав путь \\dima-21a4fe250e\sklad$\sql , туда попадаю

Haz: Dima пишет: sklad$ может он скрытую шару не понимает , простой путь без $ видит

Dima: local cDictionary:="\\dima-21a4fe250e\sklad\"+"sql\"+"temp.add" // убрал $ @ 0,0 say adsConnect60( cDictionary, 0, "ADSSYS", '', 7,@tmphh ) // .f. @ 1,1 say file(cDictionary) // .t. Пипец засада..........или прощайте SQL запросы Можно сделать через Ж... но не хочется. Расшарить можно в данном случае папку SQL на серваке и прицепить ей букву , тогда заработает ясен пень.

Haz: не пойму ток что создал шару выдал права прописал unc путь \\Mycomp\myshare\dict.add и все работает

Dima: Haz Спасибо что помогаешь. На сегодня хватит видимо. Утро вечера мудренее ;) Мож мысль во сне придет кто знает ;)

Dima: на сон грядущий тест сделал. таки да имя компа надо указывать и словарь создается а вот добавить в него базу что то пока не выходит. и скрытую шару понимает а как по IP узнать имя компа ?

Dima: ADSDDCREATE не работал с UNC в котором указан IP по причине что стоял вот такой вызов AdsLocking( .f. ) убрал , попустило , кроме того нужно указывать порт но базу пока добавить в словарь не получается это работает уже (жесть) local cDictionary:=ip_port+"\sklad$\"+"sql\"+"temp.add" ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO") Dima пишет: но базу пока добавить в словарь не получается там та же фигня и указывать нужно IP , PORT + шара ЗЫ Еще немного поседел , пока понял ;)

Dima: Haz Вот такой запрос у меня не работает и видать по тому что слово GROUP зарезервированное. "SELECT ROWID AS Recs , INDEKS INTO #TmpBase FROM volvoAT WHERE GROUP=1" Как это обойти ? Пробовал так и тож не катит "SELECT ROWID AS Recs , M.INDEKS INTO #TmpBase FROM volvoAT M WHERE M.GROUP=1"

Haz: SELECT ROWID AS Recs , INDEKS INTO #TmpBase FROM volvoAT WHERE [GROUP]=1

Dima: Haz Работает

Dima: Что то LIKE с кириллицей не пашет .......... sQlStr:="SELECT ROWID AS Recs , INDEKS INTO #TmpBase FROM volvoAT WHERE indeks like '%ПРОВ%'" а если искать в ANSI кодировке то работает , хотя база у меня OEM

Haz: Dima пишет: Что то LIKE с кириллицей не пашет пашет, что то с кодировкой скорее, протестируй в ARC32 или что то типа ANSI2OEM( 'ПРОВ' ) попробуй

Dima: как бы сказать AdsDDaddTable что бы таблица добавлялась в OEM ?

Haz: Dima пишет: как бы сказать AdsDDaddTable что бы таблица добавлялась в OEM ? в вызове есть один из параметров CHARSET, не пробовал , но уверен есть . Надо в исходник заглянуть

Dima: я пробовал но не вышло. ладно решил вопрос перекодировкой

Haz: Dima пишет: я пробовал но не вышло по этой схеме пробовал ? HB_FUNC( ADSDDADDTABLE ) { hb_retl( AdsDDAddTable( HB_ADS_PARCONNECTION( 4 ) /* hConnect */, ( UNSIGNED8 * ) hb_parcx( 1 ) /* pTableName */, ( UNSIGNED8 * ) hb_parcx( 2 ) /* pTableFileName */, ( UNSIGNED16 ) hb_ads_iFileType, ( UNSIGNED16 ) hb_ads_iCharType, ( UNSIGNED8 * ) hb_parcx( 3 ) /* pTableIndexFileName */, NULL ) == AE_SUCCESS );

Dima: да я 5-м параметром ставил 2

Dima: тут по ходу можно еще поиграть с AdsSetCharType(2, .t.)

Dima: Еще понял что если работать по старинке то есть базы открывать через USE (условно говоря) то в в самом начале проги у нас есть подключение к ADS , AdsConnect(ip_port) Так вот если в каком месте проги делать выборку через SQL запрос и подключаться к словарю вот так adsConnect60. То в дальнейшем после выхода из выборки и закрытия базы ADSSQL , основная база может отвалиться. Поэтому перед выходом я делаю переподключение , примерно так AdsConnect(ip_port) adshandle:=AdsConnection() ЗЫ Вдруг кому и пригодится.

Haz: Dima пишет: открывать через USE замени все USE cTable ALIAS cAlias на DOSQL( cAlias, "SELECT * FROM " + cTable ) и все решиться само ))) PS вроде ж убедился что по скорости не проигрываешь, а по функционалу - просто улет

Dima: а если с индексами ? при чем у меня IDX

Haz: Dima пишет: а если с индексами ? при чем у меня IDX не важно CDX IDX - сервер цепляет автоматом попробуй в одном месте ( вместо одного USe )

Dima: Haz пишет: замени все USE cTable ALIAS cAlias на DOSQL( cAlias, "SELECT * FROM " + cTable ) и все решиться само ))) что то слишком уж ты упростил ситуацию. Надо же еще и словари создать и базы туда сунуть , перед DOSQL

Dima: Haz пишет: не важно CDX IDX - сервер цепляет автоматом откуда ему знать какие индексы IDX я юзаю с той или иной базой ? )))

Haz: Dima пишет: Надо же еще и словари создать и базы туда сунуть в arc32 делов на 1 минуту ровно - создать один словарь и одним кликом добавить все dbf

Dima: Haz пишет: попробуй в одном месте ( вместо одного USe ) Допустим было USE Volvo index Volvo1,Volvo2,Volvo,test55 shared new откуда DOSQL поймет что надо прицепить еще и все эти индексы ?

Haz: Dima пишет: откуда ему знать какие индексы IDX я юзаю с той или иной базой ? ))) можно указать при добавлении таблицы в словарь IDX - поддерживается точно, но в тут удобнее CDX а еще удобнее ADI кстати скорее всего SET INDEX TO будет работать тоже

Dima: я понял. но не все сразу и возможно приду к этому ;) у тебя ADS 10.1 ?

Haz: Dima пишет: у тебя ADS 10.1 ? 10.10.0.28

Dima: Haz пишет: 10.10.0.28 Ну в смысле да. А на 11.1 нет "гены" ?

Haz: Dima пишет: нет "гены" ? поискал , не нашел , да вроде и 10 всем пока устраивает

Dima: Haz Попробую описать ситуацию на пальцах Так как я не держу все время базы открытыми а открываю и потом закрываю по мере необходимости то у меня получаются не закрытые коннекты на сервере. При чем при каждом adsConnect60 появлется новый. [pre2] базы уже открыты for i=1 to 10 adsConnect60 DOSQL browse() close adssql ......... AdsDisconnect(tmphh) // по идее отрубаюсь от adsConnect60 AdsConnect(ip_port) adshandle:=AdsConnection() next [/pre2]

Haz: Dima пишет: AdsDisconnect(tmphh) // по идее отрубаюсь от adsConnect60 У меня при старте AdsConnect а при выходе Disconnect и все работает. Делай так же а базы закрывай и открывай когда угодно.

Dima: а у меня выходит 2 ads конекта один обычный AdsConnect а другой AdsConnect60

Haz: Dima пишет: а у меня выходит 2 ads конекта один обычный AdsConnect а другой AdsConnect60 так и оставь их при входе, на выход - дисконнест а между ними любое число USE или DOSQL.

Dima: примерно так и сделал но при каждом вызове adsConnect60 растет и не уменьшается в ADS configuration utility число connections как сказать adsConnect60 что бы он использовал уже текущее подключение (хендл)

Haz: Dima пишет: при каждом вызове adsConnect60 делай всего один вызов, не пойму зачем туда сюда дергать базы уже открыты adsConnect60 for i=1 to 10 DOSQL browse() close adssql ......... next AdsDisconnect(tmphh) // по идее отрубаюсь от adsConnect60

Dima: с одним вызовом adsConnect60 не получается. Захожу в проге в меню и выбираю Каталог запчастей и его смотрю , конект к базам уже есть через adsConnect и объявлен в самом начале программы. Затем мне понадобилось установить SQL фильтр и тогда я подключаюсь к словарю через adsConnect60 и так каждый раз когда нужно установить тот или иной фильтр

Haz: Dima пишет: с одним вызовом adsConnect60 не получается 1 Запихни все dbf в словарь при помощи arc32 2 в начале программы только AdsConnect60 ( без простого AdsConnect ) 3 USE будет нормально открывать базы через словарь так обойдешься всего одним хендлом

Dima: Haz пишет: 1 Запихни все dbf в словарь при помощи arc32 2 в начале программы только AdsConnect60 ( без простого AdsConnect ) 3 USE будет нормально открывать базы через словарь так обойдешься всего одним хендлом В будущем так и сделаю. А выход кажется придумал что бы по 100 не дергать AdsConnect60. Заведу статик переменную да и всех делов и код будет выполнятся только раз

Haz: Dima пишет: А выход кажется придумал мне кажется даже два коннекта из одной проги к одному серверу не оч правильно ))) мож еще чего полезет ... кто знает, или коллизии по блокировке пойдут. попробуй все ж через словарь, а то одна нога в лыже а другая в коньке получается

Dima: Haz пишет: а то одна нога в лыже а другая в коньке получается пока так и есть

Haz: Dima пишет: пока так и есть главное что работает, хуже не бывает что то улучшать - обычно заканчивается полной переделкой всего

Dima: Вообще странно что нельзя организовать SQL запрос из под простого AdsConnect , не AdsConnect60 То ли не доработка то ли фича такая.

Haz: Dima пишет: То ли не доработка то ли фича такая. наверное это фича ADS чтоб использовать словарь. Вместо AdsConnect можно использовать AdsConnect60, а наоборот нельзя

Dima: да это я понял уже к сожалению от SQL запросов пришлось отказаться так как при старой схеме подключения через AdsConnect плюс к этому еще нормально юзать AdsConnect60 не получится. Нужно как ты и говорил базы в словарь и юзать AdsConnect60 только. Вот если бы работала AX_SetConnectionHandle тогда бы я решил проблему и смог бы вернуться на основной хэндл без переподключения (если я конечно верно понял как она работает) , но во время сборки получаю что функции такой нет.

Haz: Dima пишет: Вот если бы работала AX_SetConnectionHandle она живет в DBFAXS.LIB это что то для FiveWin , не уверен что спасет. Дима, а что мешает все dbf в словарь то пихнуть ? Просканировать папаку с базами из проги ( даже можно отдельный запихиватель/выпмхиратель написать ) и добавить автоматом. к сожалению от SQL запросов пришлось отказаться зато опыт приобрел

Dima: Ну не хочу я пока совать базы в словарь так как чую что это где то вылезет Все же жутко хочется что бы и adsConnect и adsConnect60 жили вместе. Казалось бы сложного нет ничего. В начале проги подключаемся через adsConnect и получаем MAINHANDLE Далее если нужно сделать SQL запрос то используем adsConnect60 и получаем TEMPHANDLE Поюзав оный делаем так (предварительно закрыв базу ADSSQL) AdsDisconnect(TEMPHANDLE) И вот тут нужная некая функция XYZ которая вернет меня к предыдущему и еще активному подключению XYZ(MAINHANDLE). По ходу это должно сработать ! Но что то не вижу такого в доке.

Dima: Haz До кучи и вопрос на засыпку В одной и той же проге ты подключаешься через adsConnect60 к одному серверу и через adsConnect60 к другому серверу. Хэндлы у подключений будут разные. Как ты будешь между ними переключаться ?

Haz: Dima пишет: Хэндлы у подключений будут разные. Как ты будешь между ними переключаться ? подключка идет к словарю, в SELECT можно явно указать из какого словаря брать таблицу а значит и переключаться не придется сталкивался пару лет назад , но честно не помню как именно выкрутился . Надо будет посмотреть )) помню через что то типа Create Link ... потом забыл как страшный сон , не требовалось больше.

Dima: Haz пишет: помню через что то типа Create Link завтра снова буду ковырять так как не хочется отказываться от SQL запросов

Dima: По ходу проблему решил В самом начале программы adshandle:=AdsConnection() // главный хэндл Когда нужно выполнить SQL запрос , подключаюсь к словарю через adsConnect60 и получаю новый хэндл TMPHH После того как поюзал фильтр делаю так в самом конце AdsDisconnect(tmphh) AdsConnection(adshandle,.T.) // установить текущим основное подключение через adshandle При чем если делать AdsDisconnect(tmphh) то в лог пишется ошибка 10054 говорящая лишь о принудительном отключении , по сему AdsDisconnect(tmphh) не делаю совсем и только 1 раз цепляюсь через adsConnect60 а в остальных случаях делаю AdsConnection(TMPHH,.T.) Вот вроде и все Dima пишет: При чем если делать AdsDisconnect(tmphh) то в лог пишется ошибка 10054 говорящая лишь о принудительном отключении , по сему AdsDisconnect(tmphh) Оно как бы и понятно почему возникает , так как словарь открыт. А как ему корректно сделать CLOSE ? Dima пишет: AdsConnection(adshandle,.T.) Кстати не подозревал о 2-м параметре

Haz: Dima пишет: Кстати не подозревал о 2-м параметре до сих пор тоже не подозревал, как нашел ?

Dima: Haz пишет: до сих пор тоже не подозревал, как нашел ? смотрел пример svn\harbour-trunk\harbour\contrib\rddads\tests\datad.prg в нем в комментах есть [pre2] // if you wanted to retain this connection for later, you could use // hAdminCon := AdsConnection(0) // This get/set call would return the current connection, then set it to 0 [/pre2] Ну и на удачу решил попробовать и получилось !

Haz: Dima пишет: у и на удачу решил попробовать и получилось ! может там еще какие чудеса есть а мы то не знаем

Dima: Haz пишет: может там еще какие чудеса есть а мы то не знаем хорошо бы еще такое чудо найти (надо мне) но пока не вижу Dima пишет: Dima пишет: цитата: При чем если делать AdsDisconnect(tmphh) то в лог пишется ошибка 10054 говорящая лишь о принудительном отключении , по сему AdsDisconnect(tmphh) Оно как бы и понятно почему возникает , так как словарь открыт. А как ему корректно сделать CLOSE ?

Haz: Dima пишет: Оно как бы и понятно почему возникает , так как словарь открыт. может это алиас открыт ? и на что влияет эта 10054 ( не нгашел ее в хелпе )

Dima: Haz пишет: может это алиас открыт ? ну у меня так [pre2] if tmphh==nil if !file(cDictionary) // для каждого юзера создаем свой словарик ADSDDCREATE( cDictionary,, "Словарь данных ADSDEMO",@tmphh) AdsDDaddTable( "volvoAT",ads_share+"dbf\volvo.dbf", "") AdsDDCreateUser(, alltrim(sys_name), "" , "Пользователь "+alltrim(sys_name)) Closetmphh() endif tmphh:=nil IF !adsConnect60( cDictionary,_servtype,alltrim(sys_name), , ,@tmphh ) Soob("Ошибка подключения к словарю данных","r/r","gr+/r") return nil else *AdsSetCharType(2, .t.) AdsSetDeleted(.T.) AdsRightsCheck(.f.) ENDIF else AdsConnection(tmphh,.t.) endif [/pre2] То есть мне бы хотелось закрывать временный коннект через AdsDisconnect(tmphh) но так как словарь открыт то получаю ошибку (не смертельную) 10054 и ее видно только в логе ADS. Вот и требуется каким то образом словарь в начале закрыть , но чем ? Haz пишет: и на что влияет эта 10054 ( не нгашел ее в хелпе ) В Help ее нет http://devzone.advantagedatabase.com/dz/Content.aspx?Key=17&RefNo=081204-2102

Dima: Dima пишет: Dima пишет: цитата: AdsConnection(adshandle,.T.) Кстати не подозревал о 2-м параметре По ходу я тупанул и нет 2-ого параметра Вот такой вызов AdsConnection() вернет текуший хендл подключения А вот так AdsConnection(adshandle) переключится на него [pre2] HB_FUNC( ADSCONNECTION ) /* Get/Set func to switch between connections. */ { HB_ADS_RETCONNECTION( hb_ads_getConnection() ); hb_ads_setConnection( HB_ADS_PARCONNECTION( 1 ) ); } [/pre2]

Haz: Dima пишет: А вот так AdsConnection(adshandle) переключится похоже на правду ну у меня так и нет ни одного вызова dosql ? ADS кеширует запрjсы , может перед дисконнектом кеш слить сначала ?

Dima: Haz пишет: может перед дисконнектом кеш слить сначала ? Это как ? Не пойму как у этих ребят работают SQL запросы без словарей Попробовал не получилось. http://forums.fivetechsupport.com/viewtopic.php?f=6&t=2869 Обнаружил вот такую штуку. Если после того как поработав с SQL выборкой , хочу закрыть сам словарь вот такой последовательностью AdsConnection() AdsDisconnect() AdsConnection() AdsConnection(adshandle) То при первом таком срабатывании все отлично и словарь точно закрывается и это видно по кол-ву коннектов на мониторе ADS и ошибок нет. Но стоит повторно снова подключится к словарю и поработав с SQL выборкой снова дать такую же последовательность команд то выпадает выше описанная ошибка 10054 Вроде ж не должно ее быть а она есть.

Dima: Dima пишет: Не пойму как у этих ребят работают SQL запросы без словарей Попробовал не получилось. http://forums.fivetechsupport.com/viewtopic.php?f=6&t=2869 Поспешил я с выводами. Все работает и без создания словаря базы данных. С одним ограничением. Саму базу нельзя открывать через USE (Dbusearea) если она присутствует в SQL запросе.

Haz: Dima пишет: USE (Dbusearea) если она присутствует в SQL запросе. думаю это неспроста , у меня помню были странные глюки если использовал и USE и словари

Dima: Haz пишет: думаю это неспроста , у меня помню были странные глюки если использовал и USE и словари Я не об этом писал. Речь шла о том что словарь совсем не используется а базу открываем через SQL запрос и это работает. Чуть выше ты писал что SQL запрос возможен только если используется словарь. Оказалось что это не так. Пример. Если стандартно открывать базу USE TEST SHARED NEW Browse() Если через запрос (без словаря данных) AdsCreateSqlStatement(,2) AdsExecuteSqlDirect("SELECT * FROM TEST") Browse() Правда это в разы медленнее нежели через словарь или обычным способом. Оно и понятно почему.

Dima: Haz Вопрос. Загнал я базы в словарь и затем открываю их скажем через обычный USE. Это работает , проверил. Если пытаюсь открыть любую базу вне словаря то не получается , понятно почему. Каким образом мне создать и открыть временную базу под управлением ADSCDX ?

Haz: Dima пишет: Каким образом мне создать и открыть временную базу под управлением ADSCDX ? так обычный DbCreate() работает вроде и создает базу не в словаре или так cBaseName := "Payment" cSql := "CREATE TABLE Data\" + cBaseName + "(" + ; "ID Autoinc," + ; "Date Date," + ; // "ID_OR Integer," + ; // "ID_CS Integer," + ; // "Summa Numeric( 14, 2 )," + ; // Сумма платежа "Note CIChar( 100)" + ; // прнимечание ")" IF ! FILE( cBasePath + "\Data\" + cBaseName + ".adt" ) SQL(, cSql ) AdsDDaddTable( cBaseName , "Data\" + cBaseName + ".adt", "" ) END или уже опробованным способом SELECT ... INTO #

Haz: как вариант может быть еще и то что при добавлении таблицы в словарь ADS метит ее в заголовке символом CHR(1) и таблица становится not free у ADS где то есть даже утилита для освобождения таблиц. Таблица также освобождается при удалении ее из словаря.

Dima: Haz ok

Dima: А как заставить прогу подключаться к ADS если нет сетевой платы (или в нее не вставлен кабель) Прога и ADS лежат на одном компе ? adsConnect("\\127.0.0.1:6262") // .F. ? AdsConnection() // 0 Microsoft loopback адаптер я установил , правда на нем желтый знак восклицания. Куда копать ? ЗЫ Разобрался. В качестве IP нужно давать что то типа 169.254.x.x

Vlad04: ? adsConnect("\\127.0.0.1:6262") // .F. ? AdsConnection() // 0 Я для локальной базы и локального сервера пишу так AdsConnect('C:\') ... AdsdISConnect('C:\') Иногда указываю и реальный путь, если все таблицы находятся в одном месте , или наибольшее их количество в одном месте (тогда грамматика запроса упрощается): AdsConnect('C:\Progi\dsf\') ... AdsdISConnect('C:\Progi\dsf\')

Dima: Vlad04 Да можно и так. Просто я привык использовать IP адрес.

Dima: Пересел на семерку Ранее в XP вот это работало AdsConnect("\\127.0.0.1:6262") В семерке не хочет зараза. Файер от DRWEB отключал (встроенный выключил) Если прописать прямой путь то работает. Куда копать ?

Dima: смотрю я не один http://devzone.advantagedatabase.com/dz/content.aspx?key=48&id=195150 и как же решить вопрос ?

PSP: Попробуй отключить IPv6 в свойствах сетевого адаптера.

Dima: PSP пишет: Попробуй отключить IPv6 в свойствах сетевого адаптера. Отключено

Dima: Фуф ;) Нагуглилось , работает ADS.INI в [SETTINGS] добавляем строку USE_TCP_IP=1

PSP: Dima пишет: Фуф ;) Всё гениальное - просто )))



полная версия страницы