-# $Id$
-
# Note: could be that it may not fully compile 'inline'
include $(GNUSTEP_MAKEFILES)/common.make
SUBPROJECTS += \
- skyrix-xml \
- skyrix-core \
- skyrix-sope
+ sope-xml \
+ sope-core \
+ sope-mime \
+ sope-appserver \
+ sope-ldap \
+ sope-ical \
+ sope-gdl1 \
-include $(GNUSTEP_MAKEFILES)/GNUmakefile.preamble
include $(GNUSTEP_MAKEFILES)/aggregate.make
2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+ * deprecated and moved to Recycler
+
* moved to SOPE 4.3 (v4.3.31)
2004-08-17 Helge Hess <helge.hess@opengroupware.org>
2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+ * deprecated and moved to Recycler
+
* moved to SOPE 4.3 (v4.3.25)
2004-07-19 Helge Hess <helge.hess@skyrix.com>
+++ /dev/null
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 38;
- objects = {
- 6904BAA001EB9B4900A8007E = {
- isa = PBXFileReference;
- path = CalendarField.wox;
- refType = 4;
- };
- 6904BAA101EB9B4900A8007E = {
- isa = PBXFileReference;
- path = CheckBoxMatrix.wox;
- refType = 4;
- };
- 6904BAA201EB9B4900A8007E = {
- isa = PBXFileReference;
- path = CollapsibleContent.wox;
- refType = 4;
- };
- 6904BAA301EB9B4900A8007E = {
- isa = PBXFileReference;
- path = CollapsibleContentExt.wox;
- refType = 4;
- };
- 6904BAA401EB9B4900A8007E = {
- isa = PBXFileReference;
- path = DictionaryRepetition.wox;
- refType = 4;
- };
- 6904BAA501EB9B4900A8007E = {
- isa = PBXFileReference;
- path = DnD.wox;
- refType = 4;
- };
- 6904BAA601EB9B4900A8007E = {
- isa = PBXFileReference;
- path = KeyValueConditional.wox;
- refType = 4;
- };
- 6904BAA701EB9B4900A8007E = {
- isa = PBXFileReference;
- path = ModalWindow.wox;
- refType = 4;
- };
- 6904BAA801EB9B4900A8007E = {
- isa = PBXFileReference;
- path = MonthOverview.wox;
- refType = 4;
- };
- 6904BAA901EB9B4900A8007E = {
- isa = PBXFileReference;
- path = PageView.wox;
- refType = 4;
- };
- 6904BAAA01EB9B4900A8007E = {
- isa = PBXFileReference;
- path = PanelContent.wox;
- refType = 4;
- };
- 6904BAAB01EB9B4900A8007E = {
- isa = PBXFileReference;
- path = RadioButtonMatrix.wox;
- refType = 4;
- };
- 6904BAAC01EB9B4900A8007E = {
- isa = PBXFileReference;
- path = Switch.wox;
- refType = 4;
- };
- 6904BAAD01EB9B4900A8007E = {
- isa = PBXFileReference;
- path = Table.wox;
- refType = 4;
- };
- 6904BAAE01EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TableMatrix.wox;
- refType = 4;
- };
- 6904BAAF01EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TableView.wox;
- refType = 4;
- };
- 6904BAB001EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TabPanel.wox;
- refType = 4;
- };
- 6904BAB101EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TabView.wox;
- refType = 4;
- };
- 6904BAB201EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TextFlyover.wox;
- refType = 4;
- };
- 6904BAB301EB9B4900A8007E = {
- isa = PBXFileReference;
- path = ThresholdColoredNumber.wox;
- refType = 4;
- };
- 6904BAB401EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TimeField.wox;
- refType = 4;
- };
- 6904BAB501EB9B4900A8007E = {
- isa = PBXFileReference;
- path = TreeView.wox;
- refType = 4;
- };
- 6904BAB601EB9B4900A8007E = {
- isa = PBXFileReference;
- path = ValidatedField.wox;
- refType = 4;
- };
- 6904BAB701EB9B4900A8007E = {
- isa = PBXFileReference;
- path = WeekColumnView.wox;
- refType = 4;
- };
- 6904BAB801EB9B4900A8007E = {
- isa = PBXFileReference;
- path = WeekOverview.wox;
- refType = 4;
- };
- 6905B77501CE9CDB006474DE = {
- buildStyles = (
- 6905B77701CE9CDB006474DE,
- 6905B77801CE9CDB006474DE,
- );
- isa = PBXProject;
- mainGroup = 6905B77601CE9CDB006474DE;
- productRefGroup = 6941F0270242A10C00A8007E;
- projectDirPath = "";
- targets = (
- 6918B0C201CE9E590053A783,
- 6941F0290242A10C00A8007E,
- );
- };
- 6905B77601CE9CDB006474DE = {
- children = (
- 6918B09801CE9DFF0053A783,
- 691DC05601F6197E00A8007E,
- 69AC2E89031D8E3200A8CBE9,
- 6918B09901CE9DFF0053A783,
- 6918B09A01CE9DFF0053A783,
- 6905B77901CE9D13006474DE,
- 6941F0830242A2FE00A8007E,
- 6941F0270242A10C00A8007E,
- );
- isa = PBXGroup;
- refType = 4;
- };
- 6905B77701CE9CDB006474DE = {
- buildRules = (
- );
- buildSettings = {
- COPY_PHASE_STRIP = NO;
- };
- isa = PBXBuildStyle;
- name = Development;
- };
- 6905B77801CE9CDB006474DE = {
- buildRules = (
- );
- buildSettings = {
- COPY_PHASE_STRIP = YES;
- };
- isa = PBXBuildStyle;
- name = Deployment;
- };
- 6905B77901CE9D13006474DE = {
- children = (
- 6918B09C01CE9DFF0053A783,
- 6918B09D01CE9DFF0053A783,
- 6918B09E01CE9DFF0053A783,
- 691DC04401F4D3CB00A8007E,
- 6918B09F01CE9DFF0053A783,
- 6904BAA001EB9B4900A8007E,
- 6918B0A001CE9DFF0053A783,
- 6904BAA101EB9B4900A8007E,
- 6918B0A101CE9DFF0053A783,
- 6904BAA201EB9B4900A8007E,
- 6918B0A201CE9DFF0053A783,
- 6904BAA301EB9B4900A8007E,
- 6918B0A301CE9DFF0053A783,
- 6918B0F701CEA8DF0053A783,
- 6918B0A401CE9DFF0053A783,
- 6918B0F801CEAA3F0053A783,
- 6918B0A501CE9DFF0053A783,
- 6904BAA401EB9B4900A8007E,
- 6918B0A601CE9DFF0053A783,
- 6918B0A701CE9DFF0053A783,
- 6904BAA501EB9B4900A8007E,
- 6918B0A801CE9DFF0053A783,
- 6918B0A901CE9DFF0053A783,
- 6918B0AA01CE9DFF0053A783,
- 6918B0F901CEAB5E0053A783,
- 6918B0AB01CE9DFF0053A783,
- 6904BAA601EB9B4900A8007E,
- 6918B0AC01CE9DFF0053A783,
- 6918B0AD01CE9DFF0053A783,
- 6918B0AE01CE9DFF0053A783,
- 6904BAA701EB9B4900A8007E,
- 6918B0AF01CE9DFF0053A783,
- 6904BAA801EB9B4900A8007E,
- 6918B0B001CE9DFF0053A783,
- 6904BAA901EB9B4900A8007E,
- 6918B0B101CE9DFF0053A783,
- 6904BAAA01EB9B4900A8007E,
- 6918B0B201CE9DFF0053A783,
- 6904BAAB01EB9B4900A8007E,
- 6918B0B301CE9DFF0053A783,
- 6918B0F301CEA4C20053A783,
- 6918B0B401CE9DFF0053A783,
- 6918B0F101CEA2F40053A783,
- 6918B0B501CE9DFF0053A783,
- 6904BAAC01EB9B4900A8007E,
- 6918B0B601CE9DFF0053A783,
- 6904BAAD01EB9B4900A8007E,
- 6918B0B701CE9DFF0053A783,
- 6904BAAE01EB9B4900A8007E,
- 6918B0B801CE9DFF0053A783,
- 6904BAAF01EB9B4900A8007E,
- 6918B0B901CE9DFF0053A783,
- 6904BAB001EB9B4900A8007E,
- 6918B0BA01CE9DFF0053A783,
- 6904BAB101EB9B4900A8007E,
- 6918B0BB01CE9DFF0053A783,
- 6904BAB201EB9B4900A8007E,
- 6918B0BC01CE9DFF0053A783,
- 6904BAB301EB9B4900A8007E,
- 6918B0BD01CE9DFF0053A783,
- 6904BAB401EB9B4900A8007E,
- 6918B0BE01CE9DFF0053A783,
- 6904BAB501EB9B4900A8007E,
- 6918B0BF01CE9DFF0053A783,
- 6904BAB601EB9B4900A8007E,
- 6918B0C001CE9DFF0053A783,
- 6904BAB701EB9B4900A8007E,
- 6918B0C101CE9DFF0053A783,
- 6904BAB801EB9B4900A8007E,
- );
- isa = PBXGroup;
- name = Components;
- refType = 4;
- };
- 6918B09601CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = GNUmakefile;
- refType = 4;
- };
- 6918B09701CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = GNUmakefile.preamble;
- refType = 4;
- };
- 6918B09801CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = WOxExtTest.m;
- refType = 4;
- };
- 6918B09901CE9DFF0053A783 = {
- children = (
- 6918B0C301CE9EEE0053A783,
- 6918B0C401CE9EEE0053A783,
- 6918B0C501CE9EEE0053A783,
- 6918B0C601CE9EEE0053A783,
- );
- isa = PBXGroup;
- name = Resources;
- refType = 4;
- };
- 6918B09A01CE9DFF0053A783 = {
- children = (
- 6918B09B01CE9DFF0053A783,
- 6918B0C701CE9EEE0053A783,
- 6918B0C801CE9EEE0053A783,
- 6918B0C901CE9EEE0053A783,
- 6918B0CA01CE9EEE0053A783,
- 6918B0CB01CE9EEE0053A783,
- 6918B0CC01CE9EEE0053A783,
- 6918B0CD01CE9EEE0053A783,
- 6918B0CE01CE9EEE0053A783,
- 6918B0CF01CE9EEE0053A783,
- 6918B0D001CE9EEE0053A783,
- 6918B0D101CE9EEE0053A783,
- 6918B0D201CE9EEE0053A783,
- 6918B0D301CE9EEE0053A783,
- 6918B0D401CE9EEE0053A783,
- 6918B0D501CE9EEE0053A783,
- 6918B0D601CE9EEE0053A783,
- 6918B0D701CE9EEE0053A783,
- 6918B0D801CE9EEE0053A783,
- 6918B0D901CE9EEE0053A783,
- 6918B0DA01CE9EEE0053A783,
- 6918B0DB01CE9EEE0053A783,
- 6918B0DC01CE9EEE0053A783,
- 6918B0DD01CE9EEE0053A783,
- 6918B0DE01CE9EEE0053A783,
- 6918B0DF01CE9EEE0053A783,
- 6918B0E001CE9EEE0053A783,
- 6918B0E101CE9EEE0053A783,
- 6918B0E201CE9EEE0053A783,
- 6918B0E301CE9EEE0053A783,
- 6918B0E401CE9EEE0053A783,
- 6918B0E501CE9EEE0053A783,
- 6918B0E601CE9EEE0053A783,
- 6918B0E701CE9EEE0053A783,
- 6918B0E801CE9EEE0053A783,
- 6918B0E901CE9EEE0053A783,
- 6918B0EA01CE9EEE0053A783,
- 6918B0EB01CE9EEE0053A783,
- 6918B0EC01CE9EEE0053A783,
- );
- isa = PBXGroup;
- name = WebServerResources;
- refType = 4;
- };
- 6918B09B01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = favicon.ico;
- refType = 4;
- };
- 6918B09C01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = AlertPanel.m;
- refType = 4;
- };
- 6918B09D01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = AlertPanel.wox;
- refType = 4;
- };
- 6918B09E01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Browser.m;
- refType = 4;
- };
- 6918B09F01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = CalendarField.m;
- refType = 4;
- };
- 6918B0A001CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = CheckBoxMatrix.m;
- refType = 4;
- };
- 6918B0A101CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = CollapsibleContent.m;
- refType = 4;
- };
- 6918B0A201CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = CollapsibleContentExt.m;
- refType = 4;
- };
- 6918B0A301CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = ConfirmPanel.m;
- refType = 4;
- };
- 6918B0A401CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = DateField.m;
- refType = 4;
- };
- 6918B0A501CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = DictionaryRepetition.m;
- refType = 4;
- };
- 6918B0A601CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = DirectAction.m;
- refType = 4;
- };
- 6918B0A701CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = DnD.m;
- refType = 4;
- };
- 6918B0A801CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Frame.m;
- refType = 4;
- };
- 6918B0A901CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Frame.wox;
- refType = 4;
- };
- 6918B0AA01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = ImageFlyover.m;
- refType = 4;
- };
- 6918B0AB01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = KeyValueConditional.m;
- refType = 4;
- };
- 6918B0AC01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Main.m;
- refType = 4;
- };
- 6918B0AD01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Main.wox;
- refType = 4;
- };
- 6918B0AE01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = ModalWindow.m;
- refType = 4;
- };
- 6918B0AF01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = MonthOverview.m;
- refType = 4;
- };
- 6918B0B001CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = PageView.m;
- refType = 4;
- };
- 6918B0B101CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = PanelContent.m;
- refType = 4;
- };
- 6918B0B201CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = RadioButtonMatrix.m;
- refType = 4;
- };
- 6918B0B301CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = RichString.m;
- refType = 4;
- };
- 6918B0B401CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = ShiftClick.m;
- refType = 4;
- };
- 6918B0B501CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Switch.m;
- refType = 4;
- };
- 6918B0B601CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = Table.m;
- refType = 4;
- };
- 6918B0B701CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TableMatrix.m;
- refType = 4;
- };
- 6918B0B801CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TableView.m;
- refType = 4;
- };
- 6918B0B901CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TabPanel.m;
- refType = 4;
- };
- 6918B0BA01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TabView.m;
- refType = 4;
- };
- 6918B0BB01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TextFlyover.m;
- refType = 4;
- };
- 6918B0BC01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = ThresholdColoredNumber.m;
- refType = 4;
- };
- 6918B0BD01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TimeField.m;
- refType = 4;
- };
- 6918B0BE01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = TreeView.m;
- refType = 4;
- };
- 6918B0BF01CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = ValidatedField.m;
- refType = 4;
- };
- 6918B0C001CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = WeekColumnView.m;
- refType = 4;
- };
- 6918B0C101CE9DFF0053A783 = {
- isa = PBXFileReference;
- path = WeekOverview.m;
- refType = 4;
- };
- 6918B0C201CE9E590053A783 = {
- buildArgumentsString = $ACTION;
- buildPhases = (
- );
- buildSettings = {
- OTHER_CFLAGS = "";
- OTHER_LDFLAGS = "";
- OTHER_REZFLAGS = "";
- PRODUCT_NAME = "gs-WOxExtTest";
- SECTORDER_FLAGS = "";
- WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
- debug = yes;
- shared = yes;
- };
- buildToolPath = /usr/bin/gnumake;
- dependencies = (
- );
- isa = PBXLegacyTarget;
- name = "gs-WOxExtTest";
- productName = "gs-WOxExtTest";
- settingsToExpand = 6;
- settingsToPassInEnvironment = 287;
- settingsToPassOnCommandLine = 280;
- shouldUseHeadermap = 0;
- };
- 6918B0C301CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = appointments.plist;
- path = Resources/appointments.plist;
- refType = 4;
- };
- 6918B0C401CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = Dictionary.plist;
- path = Resources/Dictionary.plist;
- refType = 4;
- };
- 6918B0C501CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = TableView.plist;
- path = Resources/TableView.plist;
- refType = 4;
- };
- 6918B0C601CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = TreeView.plist;
- path = Resources/TreeView.plist;
- refType = 4;
- };
- 6918B0C701CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = collapsed.gif;
- path = WebServerResources/collapsed.gif;
- refType = 4;
- };
- 6918B0C801CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = corner_left.gif;
- path = WebServerResources/corner_left.gif;
- refType = 4;
- };
- 6918B0C901CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = corner_right.gif;
- path = WebServerResources/corner_right.gif;
- refType = 4;
- };
- 6918B0CA01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = downward_sorted.gif;
- path = WebServerResources/downward_sorted.gif;
- refType = 4;
- };
- 6918B0CB01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = expanded.gif;
- path = WebServerResources/expanded.gif;
- refType = 4;
- };
- 6918B0CC01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = first_blind.gif;
- path = WebServerResources/first_blind.gif;
- refType = 4;
- };
- 6918B0CD01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = first.gif;
- path = WebServerResources/first.gif;
- refType = 4;
- };
- 6918B0CE01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = folder_closed.gif;
- path = WebServerResources/folder_closed.gif;
- refType = 4;
- };
- 6918B0CF01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = folder_opened.gif;
- path = WebServerResources/folder_opened.gif;
- refType = 4;
- };
- 6918B0D001CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = last_blind.gif;
- path = WebServerResources/last_blind.gif;
- refType = 4;
- };
- 6918B0D101CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = last.gif;
- path = WebServerResources/last.gif;
- refType = 4;
- };
- 6918B0D201CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = menu_email_inactive.gif;
- path = WebServerResources/menu_email_inactive.gif;
- refType = 4;
- };
- 6918B0D301CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = menu_email.gif;
- path = WebServerResources/menu_email.gif;
- refType = 4;
- };
- 6918B0D401CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = next_blind.gif;
- path = WebServerResources/next_blind.gif;
- refType = 4;
- };
- 6918B0D501CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = next.gif;
- path = WebServerResources/next.gif;
- refType = 4;
- };
- 6918B0D601CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = non_sorted.gif;
- path = WebServerResources/non_sorted.gif;
- refType = 4;
- };
- 6918B0D701CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = previous_blind.gif;
- path = WebServerResources/previous_blind.gif;
- refType = 4;
- };
- 6918B0D801CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = previous.gif;
- path = WebServerResources/previous.gif;
- refType = 4;
- };
- 6918B0D901CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_news_left.gif;
- path = WebServerResources/tab_news_left.gif;
- refType = 4;
- };
- 6918B0DA01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_news_selected.gif;
- path = WebServerResources/tab_news_selected.gif;
- refType = 4;
- };
- 6918B0DB01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_news.gif;
- path = WebServerResources/tab_news.gif;
- refType = 4;
- };
- 6918B0DC01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_persons_left.gif;
- path = WebServerResources/tab_persons_left.gif;
- refType = 4;
- };
- 6918B0DD01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_persons_selected.gif;
- path = WebServerResources/tab_persons_selected.gif;
- refType = 4;
- };
- 6918B0DE01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_persons.gif;
- path = WebServerResources/tab_persons.gif;
- refType = 4;
- };
- 6918B0DF01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_projects_left.gif;
- path = WebServerResources/tab_projects_left.gif;
- refType = 4;
- };
- 6918B0E001CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_projects_selected.gif;
- path = WebServerResources/tab_projects_selected.gif;
- refType = 4;
- };
- 6918B0E101CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = tab_projects.gif;
- path = WebServerResources/tab_projects.gif;
- refType = 4;
- };
- 6918B0E201CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_corner_minus.gif;
- path = WebServerResources/treeview_corner_minus.gif;
- refType = 4;
- };
- 6918B0E301CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_corner_plus.gif;
- path = WebServerResources/treeview_corner_plus.gif;
- refType = 4;
- };
- 6918B0E401CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_corner.gif;
- path = WebServerResources/treeview_corner.gif;
- refType = 4;
- };
- 6918B0E501CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_junction.gif;
- path = WebServerResources/treeview_junction.gif;
- refType = 4;
- };
- 6918B0E601CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_leaf_corner.gif;
- path = WebServerResources/treeview_leaf_corner.gif;
- refType = 4;
- };
- 6918B0E701CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_leaf.gif;
- path = WebServerResources/treeview_leaf.gif;
- refType = 4;
- };
- 6918B0E801CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_line.gif;
- path = WebServerResources/treeview_line.gif;
- refType = 4;
- };
- 6918B0E901CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_minus.gif;
- path = WebServerResources/treeview_minus.gif;
- refType = 4;
- };
- 6918B0EA01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_plus.gif;
- path = WebServerResources/treeview_plus.gif;
- refType = 4;
- };
- 6918B0EB01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = treeview_space.gif;
- path = WebServerResources/treeview_space.gif;
- refType = 4;
- };
- 6918B0EC01CE9EEE0053A783 = {
- isa = PBXFileReference;
- name = upward_sorted.gif;
- path = WebServerResources/upward_sorted.gif;
- refType = 4;
- };
- 6918B0F101CEA2F40053A783 = {
- isa = PBXFileReference;
- path = ShiftClick.wox;
- refType = 4;
- };
- 6918B0F301CEA4C20053A783 = {
- isa = PBXFileReference;
- path = RichString.wox;
- refType = 4;
- };
- 6918B0F701CEA8DF0053A783 = {
- isa = PBXFileReference;
- path = ConfirmPanel.wox;
- refType = 4;
- };
- 6918B0F801CEAA3F0053A783 = {
- isa = PBXFileReference;
- path = DateField.wox;
- refType = 4;
- };
- 6918B0F901CEAB5E0053A783 = {
- isa = PBXFileReference;
- path = ImageFlyover.wox;
- refType = 4;
- };
- 691DC04401F4D3CB00A8007E = {
- isa = PBXFileReference;
- path = Browser.wox;
- refType = 4;
- };
- 691DC05601F6197E00A8007E = {
- isa = PBXFileReference;
- path = common.h;
- refType = 4;
- };
- 6941F0270242A10C00A8007E = {
- children = (
- 6941F0280242A10C00A8007E,
- );
- isa = PBXGroup;
- name = Products;
- refType = 4;
- };
- 6941F0280242A10C00A8007E = {
- isa = PBXApplicationReference;
- path = WOxExtTest.woa;
- refType = 3;
- };
- 6941F0290242A10C00A8007E = {
- buildPhases = (
- 6941F02A0242A10C00A8007E,
- 6941F02B0242A10C00A8007E,
- 6941F04A0242A10C00A8007E,
- 6941F06C0242A10C00A8007E,
- 6941F06D0242A10C00A8007E,
- );
- buildSettings = {
- FRAMEWORK_SEARCH_PATHS = /Users/helge/build;
- OTHER_CFLAGS = "-DCOCOA_Foundation_LIBRARY=1 -DNeXT_Foundation_LIBRARY=1 -DNeXT_RUNTIME=1";
- OTHER_LDFLAGS = "";
- OTHER_REZFLAGS = "";
- PRODUCT_NAME = WOxExtTest;
- SECTORDER_FLAGS = "";
- WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
- WRAPPER_EXTENSION = woa;
- };
- dependencies = (
- );
- isa = PBXApplicationTarget;
- name = WOxExtTest;
- productInstallPath = "$(USER_APPS_DIR)";
- productName = WOxExtTest;
- productReference = 6941F0280242A10C00A8007E;
- productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
-<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
-<plist version=\"1.0\">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleExecutable</key>
- <string></string>
- <key>CFBundleGetInfoString</key>
- <string></string>
- <key>CFBundleIconFile</key>
- <string></string>
- <key>CFBundleIdentifier</key>
- <string>com.skyrix.WOxExtTest</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string></string>
- <key>CFBundlePackageType</key>
- <string>BDNL</string>
- <key>CFBundleShortVersionString</key>
- <string></string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>4.2</string>
-</dict>
-</plist>
-";
- shouldUseHeadermap = 0;
- };
- 6941F02A0242A10C00A8007E = {
- buildActionMask = 2147483647;
- files = (
- 6941F0760242A19200A8007E,
- );
- isa = PBXHeadersBuildPhase;
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6941F02B0242A10C00A8007E = {
- buildActionMask = 2147483647;
- files = (
- 6941F02C0242A10C00A8007E,
- 6941F02D0242A10C00A8007E,
- 6941F02E0242A10C00A8007E,
- 6941F02F0242A10C00A8007E,
- 6941F0300242A10C00A8007E,
- 6941F0310242A10C00A8007E,
- 6941F0320242A10C00A8007E,
- 6941F0330242A10C00A8007E,
- 6941F0340242A10C00A8007E,
- 6941F0350242A10C00A8007E,
- 6941F0360242A10C00A8007E,
- 6941F0370242A10C00A8007E,
- 6941F0380242A10C00A8007E,
- 6941F0390242A10C00A8007E,
- 6941F03A0242A10C00A8007E,
- 6941F03B0242A10C00A8007E,
- 6941F03C0242A10C00A8007E,
- 6941F03D0242A10C00A8007E,
- 6941F03E0242A10C00A8007E,
- 6941F03F0242A10C00A8007E,
- 6941F0400242A10C00A8007E,
- 6941F0410242A10C00A8007E,
- 6941F0420242A10C00A8007E,
- 6941F0430242A10C00A8007E,
- 6941F0440242A10C00A8007E,
- 6941F0450242A10C00A8007E,
- 6941F0460242A10C00A8007E,
- 6941F0470242A10C00A8007E,
- 6941F0480242A10C00A8007E,
- 6941F0490242A10C00A8007E,
- 6941F06F0242A18300A8007E,
- 6941F0700242A18300A8007E,
- 6941F0710242A18300A8007E,
- 6941F0720242A18300A8007E,
- 6941F0770242A19200A8007E,
- 6941F0780242A19200A8007E,
- 6941F0790242A19200A8007E,
- 6941F07A0242A19200A8007E,
- 69FC79A902983FB40083626D,
- 69FC79AA02983FB50083626D,
- 69FC79AB02983FB60083626D,
- 69FC79AC02983FB60083626D,
- 69FC79AD02983FB70083626D,
- 69FC79AE02983FB70083626D,
- 69FC79AF02983FB80083626D,
- 69FC79B002983FB80083626D,
- 69FC79B202983FBA0083626D,
- 69FC79B302983FBA0083626D,
- 69FC79B402983FBB0083626D,
- 69FC79B502983FBC0083626D,
- 69FC79B602983FBD0083626D,
- 69FC79B702983FBD0083626D,
- 69FC79B802983FBE0083626D,
- 69FC79B902983FBE0083626D,
- 69FC79BA02983FBF0083626D,
- 69FC79BB02983FC00083626D,
- 69FC79BC02983FC00083626D,
- 69FC79BD02983FC10083626D,
- 69FC79BE02983FC10083626D,
- 69FC79BF02983FC40083626D,
- 69FC79C002983FC40083626D,
- 69FC79C102983FC50083626D,
- 69FC79C202983FC50083626D,
- 69FC79C302983FC60083626D,
- 69FC79C402983FC60083626D,
- 69FC79C502983FCC0083626D,
- 69FC79C602983FCD0083626D,
- 69FC79C702983FCD0083626D,
- 69FC79C802983FCE0083626D,
- 69FC79C902983FCE0083626D,
- 69FC79CA02983FCF0083626D,
- 69FC79CB02983FCF0083626D,
- 69FC79CC02983FD00083626D,
- 69FC79CD02983FD00083626D,
- 69FC79CE02983FD40083626D,
- 69FC79CF02983FD70083626D,
- 69FC79D002983FD80083626D,
- );
- isa = PBXResourcesBuildPhase;
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6941F02C0242A10C00A8007E = {
- fileRef = 6918B09D01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F02D0242A10C00A8007E = {
- fileRef = 691DC04401F4D3CB00A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F02E0242A10C00A8007E = {
- fileRef = 6904BAA001EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F02F0242A10C00A8007E = {
- fileRef = 6904BAA101EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0300242A10C00A8007E = {
- fileRef = 6904BAA201EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0310242A10C00A8007E = {
- fileRef = 6904BAA301EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0320242A10C00A8007E = {
- fileRef = 6918B0F701CEA8DF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0330242A10C00A8007E = {
- fileRef = 6918B0F801CEAA3F0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0340242A10C00A8007E = {
- fileRef = 6904BAA401EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0350242A10C00A8007E = {
- fileRef = 6904BAA501EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0360242A10C00A8007E = {
- fileRef = 6918B0A901CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0370242A10C00A8007E = {
- fileRef = 6918B0F901CEAB5E0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0380242A10C00A8007E = {
- fileRef = 6904BAA601EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0390242A10C00A8007E = {
- fileRef = 6918B0AD01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F03A0242A10C00A8007E = {
- fileRef = 6904BAA701EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F03B0242A10C00A8007E = {
- fileRef = 6904BAA801EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F03C0242A10C00A8007E = {
- fileRef = 6904BAA901EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F03D0242A10C00A8007E = {
- fileRef = 6904BAAA01EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F03E0242A10C00A8007E = {
- fileRef = 6904BAAB01EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F03F0242A10C00A8007E = {
- fileRef = 6918B0F301CEA4C20053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0400242A10C00A8007E = {
- fileRef = 6918B0F101CEA2F40053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0410242A10C00A8007E = {
- fileRef = 6904BAAC01EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0420242A10C00A8007E = {
- fileRef = 6904BAAD01EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0430242A10C00A8007E = {
- fileRef = 6904BAAE01EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0440242A10C00A8007E = {
- fileRef = 6904BAAF01EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0450242A10C00A8007E = {
- fileRef = 6904BAB001EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0460242A10C00A8007E = {
- fileRef = 6904BAB101EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0470242A10C00A8007E = {
- fileRef = 6904BAB201EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0480242A10C00A8007E = {
- fileRef = 6904BAB301EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0490242A10C00A8007E = {
- fileRef = 6904BAB401EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F04A0242A10C00A8007E = {
- buildActionMask = 2147483647;
- files = (
- 6941F04B0242A10C00A8007E,
- 6941F04C0242A10C00A8007E,
- 6941F04D0242A10C00A8007E,
- 6941F04E0242A10C00A8007E,
- 6941F04F0242A10C00A8007E,
- 6941F0500242A10C00A8007E,
- 6941F0510242A10C00A8007E,
- 6941F0520242A10C00A8007E,
- 6941F0530242A10C00A8007E,
- 6941F0540242A10C00A8007E,
- 6941F0550242A10C00A8007E,
- 6941F0560242A10C00A8007E,
- 6941F0570242A10C00A8007E,
- 6941F0580242A10C00A8007E,
- 6941F0590242A10C00A8007E,
- 6941F05A0242A10C00A8007E,
- 6941F05B0242A10C00A8007E,
- 6941F05C0242A10C00A8007E,
- 6941F05D0242A10C00A8007E,
- 6941F05E0242A10C00A8007E,
- 6941F05F0242A10C00A8007E,
- 6941F0600242A10C00A8007E,
- 6941F0610242A10C00A8007E,
- 6941F0620242A10C00A8007E,
- 6941F0630242A10C00A8007E,
- 6941F0640242A10C00A8007E,
- 6941F0650242A10C00A8007E,
- 6941F0660242A10C00A8007E,
- 6941F0670242A10C00A8007E,
- 6941F0680242A10C00A8007E,
- 6941F0690242A10C00A8007E,
- 6941F06A0242A10C00A8007E,
- 6941F06B0242A10C00A8007E,
- 6941F0730242A18300A8007E,
- 6941F0740242A18300A8007E,
- 6941F0750242A18300A8007E,
- );
- isa = PBXSourcesBuildPhase;
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6941F04B0242A10C00A8007E = {
- fileRef = 6918B09801CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F04C0242A10C00A8007E = {
- fileRef = 6918B09C01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F04D0242A10C00A8007E = {
- fileRef = 6918B09E01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F04E0242A10C00A8007E = {
- fileRef = 6918B09F01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F04F0242A10C00A8007E = {
- fileRef = 6918B0A001CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0500242A10C00A8007E = {
- fileRef = 6918B0A101CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0510242A10C00A8007E = {
- fileRef = 6918B0A201CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0520242A10C00A8007E = {
- fileRef = 6918B0A301CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0530242A10C00A8007E = {
- fileRef = 6918B0A401CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0540242A10C00A8007E = {
- fileRef = 6918B0A501CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0550242A10C00A8007E = {
- fileRef = 6918B0A601CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0560242A10C00A8007E = {
- fileRef = 6918B0A701CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0570242A10C00A8007E = {
- fileRef = 6918B0A801CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0580242A10C00A8007E = {
- fileRef = 6918B0AA01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0590242A10C00A8007E = {
- fileRef = 6918B0AB01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F05A0242A10C00A8007E = {
- fileRef = 6918B0AC01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F05B0242A10C00A8007E = {
- fileRef = 6918B0AE01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F05C0242A10C00A8007E = {
- fileRef = 6918B0AF01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F05D0242A10C00A8007E = {
- fileRef = 6918B0B001CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F05E0242A10C00A8007E = {
- fileRef = 6918B0B101CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F05F0242A10C00A8007E = {
- fileRef = 6918B0B201CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0600242A10C00A8007E = {
- fileRef = 6918B0B301CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0610242A10C00A8007E = {
- fileRef = 6918B0B401CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0620242A10C00A8007E = {
- fileRef = 6918B0B501CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0630242A10C00A8007E = {
- fileRef = 6918B0B601CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0640242A10C00A8007E = {
- fileRef = 6918B0B701CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0650242A10C00A8007E = {
- fileRef = 6918B0B801CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0660242A10C00A8007E = {
- fileRef = 6918B0B901CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0670242A10C00A8007E = {
- fileRef = 6918B0BA01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0680242A10C00A8007E = {
- fileRef = 6918B0BB01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0690242A10C00A8007E = {
- fileRef = 6918B0BC01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F06A0242A10C00A8007E = {
- fileRef = 6918B0BD01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F06B0242A10C00A8007E = {
- fileRef = 6918B0BE01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F06C0242A10C00A8007E = {
- buildActionMask = 2147483647;
- files = (
- 6941F07F0242A1F300A8007E,
- 6941F0800242A1F300A8007E,
- 6941F0850242A2FE00A8007E,
- );
- isa = PBXFrameworksBuildPhase;
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6941F06D0242A10C00A8007E = {
- buildActionMask = 2147483647;
- files = (
- );
- isa = PBXRezBuildPhase;
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6941F06F0242A18300A8007E = {
- fileRef = 6904BAB501EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0700242A18300A8007E = {
- fileRef = 6904BAB601EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0710242A18300A8007E = {
- fileRef = 6904BAB701EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0720242A18300A8007E = {
- fileRef = 6904BAB801EB9B4900A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0730242A18300A8007E = {
- fileRef = 6918B0BF01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0740242A18300A8007E = {
- fileRef = 6918B0C001CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0750242A18300A8007E = {
- fileRef = 6918B0C101CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0760242A19200A8007E = {
- fileRef = 691DC05601F6197E00A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0770242A19200A8007E = {
- fileRef = 6918B0C301CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0780242A19200A8007E = {
- fileRef = 6918B0C401CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0790242A19200A8007E = {
- fileRef = 6918B0C501CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F07A0242A19200A8007E = {
- fileRef = 6918B0C601CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F07B0242A1F300A8007E = {
- isa = PBXFrameworkReference;
- name = FoundationExt.framework;
- path = /Users/helge/build/FoundationExt.framework;
- refType = 0;
- };
- 6941F07C0242A1F300A8007E = {
- isa = PBXFrameworkReference;
- name = NGObjWeb.framework;
- path = /Users/helge/build/NGObjWeb.framework;
- refType = 0;
- };
- 6941F07F0242A1F300A8007E = {
- fileRef = 6941F07B0242A1F300A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0800242A1F300A8007E = {
- fileRef = 6941F07C0242A1F300A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 6941F0830242A2FE00A8007E = {
- children = (
- 6941F07C0242A1F300A8007E,
- 6941F07B0242A1F300A8007E,
- 6941F0840242A2FE00A8007E,
- );
- isa = PBXGroup;
- name = "Linked Frameworks";
- refType = 4;
- };
- 6941F0840242A2FE00A8007E = {
- isa = PBXFrameworkReference;
- name = Foundation.framework;
- path = /System/Library/Frameworks/Foundation.framework;
- refType = 0;
- };
- 6941F0850242A2FE00A8007E = {
- fileRef = 6941F0840242A2FE00A8007E;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69AC2E89031D8E3200A8CBE9 = {
- children = (
- 6918B09601CE9DFF0053A783,
- 6918B09701CE9DFF0053A783,
- );
- isa = PBXGroup;
- name = Makefiles;
- refType = 4;
- };
- 69FC79A902983FB40083626D = {
- fileRef = 6918B09B01CE9DFF0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79AA02983FB50083626D = {
- fileRef = 6918B0C701CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79AB02983FB60083626D = {
- fileRef = 6918B0C801CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79AC02983FB60083626D = {
- fileRef = 6918B0C901CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79AD02983FB70083626D = {
- fileRef = 6918B0CA01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79AE02983FB70083626D = {
- fileRef = 6918B0CB01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79AF02983FB80083626D = {
- fileRef = 6918B0CC01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B002983FB80083626D = {
- fileRef = 6918B0CD01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B202983FBA0083626D = {
- fileRef = 6918B0D001CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B302983FBA0083626D = {
- fileRef = 6918B0CF01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B402983FBB0083626D = {
- fileRef = 6918B0CE01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B502983FBC0083626D = {
- fileRef = 6918B0D101CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B602983FBD0083626D = {
- fileRef = 6918B0D201CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B702983FBD0083626D = {
- fileRef = 6918B0D301CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B802983FBE0083626D = {
- fileRef = 6918B0D401CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79B902983FBE0083626D = {
- fileRef = 6918B0D501CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79BA02983FBF0083626D = {
- fileRef = 6918B0D701CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79BB02983FC00083626D = {
- fileRef = 6918B0D601CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79BC02983FC00083626D = {
- fileRef = 6918B0D801CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79BD02983FC10083626D = {
- fileRef = 6918B0D901CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79BE02983FC10083626D = {
- fileRef = 6918B0DA01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79BF02983FC40083626D = {
- fileRef = 6918B0DB01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C002983FC40083626D = {
- fileRef = 6918B0DC01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C102983FC50083626D = {
- fileRef = 6918B0DD01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C202983FC50083626D = {
- fileRef = 6918B0DE01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C302983FC60083626D = {
- fileRef = 6918B0DF01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C402983FC60083626D = {
- fileRef = 6918B0E001CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C502983FCC0083626D = {
- fileRef = 6918B0E101CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C602983FCD0083626D = {
- fileRef = 6918B0E201CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C702983FCD0083626D = {
- fileRef = 6918B0E301CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C802983FCE0083626D = {
- fileRef = 6918B0E401CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79C902983FCE0083626D = {
- fileRef = 6918B0E501CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79CA02983FCF0083626D = {
- fileRef = 6918B0E601CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79CB02983FCF0083626D = {
- fileRef = 6918B0E701CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79CC02983FD00083626D = {
- fileRef = 6918B0E801CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79CD02983FD00083626D = {
- fileRef = 6918B0E901CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79CE02983FD40083626D = {
- fileRef = 6918B0EA01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79CF02983FD70083626D = {
- fileRef = 6918B0EC01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- 69FC79D002983FD80083626D = {
- fileRef = 6918B0EB01CE9EEE0053A783;
- isa = PBXBuildFile;
- settings = {
- };
- };
- };
- rootObject = 6905B77501CE9CDB006474DE;
-}
-# $Id$
-
include $(GNUSTEP_MAKEFILES)/common.make
-PACKAGE_NAME=skyrix-core
-VERSION=4.2.0
+PACKAGE_NAME=sope-core
+VERSION=4.3.0
SUBPROJECTS = \
EOControl \
NGExtensions \
NGStreams \
- NGMime \
- NGLdap \
- NGiCal \
include $(GNUSTEP_MAKEFILES)/aggregate.make
-
-autodoc :
- (cd EOControl; $(MAKE) autodoc)
- (cd NGExtensions; $(MAKE) autodoc)
- (cd NGStreams; $(MAKE) autodoc)
- (cd NGMime; $(MAKE) autodoc)
- (cd NGLdap; $(MAKE) autodoc)
Prerequisites:
- Apple Developer Tools
-- skyrix-xml
+- sope-xml
There are two ways to build SOPE on MacOSX, either using the gnustep-make
package or as native Xcode projects. The first option is usually used when
0xC1000000 EOControl
0xC1200000 NGExtensions
0xC1400000 NGStreams
-0xC1600000 NGImap4 [not available with gstep-make]
-0xC1800000 NGMail [not available with gstep-make]
-0xC1A00000 NGMime [used as base in gstep-make]
-0xC1C00000 NGLdap
-0xC1E00000 NGiCal
0xC2FF0000 SxCore
--- /dev/null
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
--- /dev/null
+2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+
+ * moved from ThirdParty to SOPE/sope-gdl1 (v1.0.2)
+
+2003-05-07 Helge Hess <helge.hess@skyrix.com>
+
+ * v1.0.1
+
+ * replaced all THROW macros with -raise calls, this was necessary with
+ the new gcc 3.3 preprocessor for compilation
+
+ * GNUmakefile (FrontBase2_RESOURCE_FILES): added a Version file
+
+Mon May 5 16:08:07 2003 Jan Reichmann <jan@skyrix.com>
+
+ * FBValues.m: code cleanups, fixed retain bug (NSData valueFromBytes)
+
+Wed Mar 26 10:23:53 2003 Jan Reichmann <jan@skyrix.com>
+
+ * FBChannel.m: add debugging-logs if channel will be closed
+
+Mon Dec 23 18:22:18 2002 Helge Hess <helge.hess@skyrix.com>
+
+ * FBChannel.m: fixed a gcc 3.2 warning
+
+Fri Nov 29 15:17:04 2002 <jan@skyrix.com>
+
+ * FBChannel.m: from 4.1
+
+Tue Sep 3 15:32:24 2002 Jan Reichmann <jan@skyrix.com>
+
+ * FBChannel.m: values comes now from self->selectedAttributes
+ * FBValues.m: add missing Frontbase type to NSNumber -valueFromBytes
+ (FB_VCharacter)
+
+2002-08-30 Helge Hess <helge.hess@skyrix.com>
+
+ * GNUmakefile.preamble (FrontBase2_BUNDLE_LIBS): fixed a bug in the
+ Makefile (did compile without prior installation of GDLAccess)
+
+Wed Aug 21 17:55:25 2002 Jan Reichmann <jan@skyrix.com>
+
+ * FBChannel.m: (from 4.1)
+ -use _attributes-var (model) for creating attr-row
+ -fixed '\0' bug (empty password must be set to '\0')
+ -fixed login with passwd bug (pwd will be only accepted,
+ if it isn`t crypted with fbcDigestPassword
+
+Fri Jul 27 10:22:18 2001 Helge Hess <helge.hess@skyrix.com>
+
+ * FBChannel.m: close channel on -dealloc
+
+Wed Jan 3 19:15:59 2001 Jan Reichmann <jan@skyrix.com>
+
+ * FBChannel.m, FBChannel+Model.m: cache table informations
+
+Wed Jan 3 18:51:28 2001 Jan Reichmann <jan@skyrix.com>
+
+ * FBAdaptor+Types.m, EOAttribute+FB.m: INT -> INTEGER
+
+Tue Jan 2 14:42:20 2001 Jan Reichmann <jan@skyrix.com>
+
+ * FBChannel.m: fixed core dump if password is wrong
+
+Wed Dec 6 12:48:58 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * renamed file FBAdaptor to FrontBase2Adaptor, renamed FrontBaseAdaptor
+ class to FrontBase2Adaptor
+
+Mon Dec 4 13:31:07 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * GNUmakefile: added cancompile.sh script and support
+
+Fri Nov 17 15:46:43 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * created FB2 adaptor out of FB1 adaptor ..
+
+Wed Aug 23 16:56:28 2000 Joerg Grimm <joerg@trex2>
+
+ * FBAdaptor.m: formatting for text attributes added
+
+Mon May 29 15:56:58 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * FBChannel.m: automagically add sort-ordering attributes to query set
+
+Mon Apr 10 17:54:39 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * FBValues.m ([NSCalendarDate -stringValueForFrontBaseType:attribute:]):
+ removed a NSLog
+
+Mon Apr 10 12:25:38 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * FBChannel.m: fixed memory free bug
+
+Tue Feb 29 19:30:46 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * MOF3 import
+
+Fri Nov 12 14:35:05 1999 Helge Hess <helge.hess@mdlink.de>
+
+ * added support for user and database authentication
+
+Tue Nov 2 16:52:47 1999 Helge Hess <helge.hess@mdlink.de>
+
+ * FBAdaptor.m: fixed -charConvertExpression..
+
+Thu Oct 7 13:50:48 1999 Helge Hess <helge.hess@mdlink.de>
+
+ * created ChangeLog for FrontBase adaptor
--- /dev/null
+/*
+ EOAttribute+FB.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAttribute+FB.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_EOAttribute_H___
+#define ___FB_EOAttribute_H___
+
+#import <GDLAccess/EOAttribute.h>
+
+@class NSString;
+
+@interface EOAttribute(FBAttributeAdditions)
+
+- (void)loadValueClassForExternalFrontBaseType:(NSString *)_type;
+- (void)loadValueClassAndTypeFromFrontBaseType:(int)_type;
+//- (void)loadValueClassAndTypeFromSybaseDataFmt:(CS_DATAFMT *)_type;
+
+@end
+
+#endif
--- /dev/null
+/*
+ EOAttribute+FB.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAttribute+FB.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOAttribute+FB.h"
+#import <FBCAccess/FBCAccess.h>
+
+// Frontbase Date: Oct 21 1997 21:52:26+08:00
+static NSString *FRONTBASE_DATE_FORMAT = @"%Y-%m-%d %H:%M:%S";
+
+@implementation EOAttribute(FBAttributeAdditions)
+
+- (void)loadValueClassForExternalFrontBaseType:(NSString *)_type {
+ _type = [_type lowercaseString];
+
+ if ([_type isEqualToString:@"tinyint"] ||
+ [_type isEqualToString:@"bit"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ }
+ else if ([_type isEqualToString:@"smallint"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ }
+ else if ([_type isEqualToString:@"int"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ }
+ else if ([_type isEqualToString:@"char"] ||
+ [_type isEqualToString:@"varchar"]) {
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"date"] ||
+ [_type isEqualToString:@"timestamp"] ||
+ [_type isEqualToString:@"timestamp with time zone"]) {
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:FRONTBASE_DATE_FORMAT];
+ }
+ else if ([_type isEqualToString:@"float"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"f"];
+ }
+ else if ([_type isEqualToString:@"time"] ||
+ [_type isEqualToString:@"time with time zone"]) {
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"real"] ||
+ [_type isEqualToString:@"money"] ||
+ [_type isEqualToString:@"money4"] ||
+ [_type isEqualToString:@"decimal"] ||
+ [_type isEqualToString:@"numeric"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ }
+ else if ([_type isEqualToString:@"BLOB"]) {
+ [self setValueClassName:@"NSData"];
+ }
+ else if ([_type isEqualToString:@"CLOB"]) {
+ [self setValueClassName:@"NSString"];
+ }
+ else {
+ NSLog(@"invalid argument %@", _type);
+
+ [InvalidArgumentException raise:@"InvalidArgumentException"
+ format:
+ @"invalid FrontBase type %@ passed to -%@",
+ _type, NSStringFromSelector(_cmd)];
+ }
+}
+
+- (void)loadValueClassAndTypeFromFrontBaseType:(int)_type {
+ switch (_type) {
+ case FB_Boolean:
+ [self setExternalType:@"BOOLEAN"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ break;
+
+ case FB_Integer:
+ [self setExternalType:@"INTEGER"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ break;
+ case FB_SmallInteger:
+ [self setExternalType:@"SMALLINT"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ break;
+
+ case FB_Float:
+ [self setExternalType:@"FLOAT"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ break;
+ case FB_Real:
+ [self setExternalType:@"REAL"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ break;
+ case FB_Double:
+ [self setExternalType:@"DOUBLE"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ break;
+ case FB_Numeric:
+ [self setExternalType:@"NUMERIC"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ break;
+ case FB_Decimal:
+ [self setExternalType:@"DECIMAL"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ break;
+
+ case FB_Character:
+ [self setExternalType:@"CHAR"];
+ [self setValueClassName:@"NSString"];
+ break;
+ case FB_VCharacter:
+ [self setExternalType:@"VARCHAR"];
+ [self setValueClassName:@"NSString"];
+ break;
+
+ case FB_Bit:
+ [self setExternalType:@"BIT"];
+ [self setValueClassName:@"NSData"];
+ break;
+ case FB_VBit:
+ [self setExternalType:@"VARBIT"];
+ [self setValueClassName:@"NSData"];
+ break;
+
+ case FB_Date:
+ [self setExternalType:@"DATE"];
+ [self setValueClassName:@"NSCalendarDate"];
+ break;
+
+ case FB_Time:
+ [self setExternalType:@"TIME"];
+ [self setValueClassName:@"NSString"];
+ break;
+ case FB_TimeTZ:
+ [self setExternalType:@"TIME WITH TIME ZONE"];
+ [self setValueClassName:@"NSString"];
+ break;
+
+ case FB_Timestamp:
+ [self setExternalType:@"TIMESTAMP"];
+ [self setValueClassName:@"NSCalendarDate"];
+ break;
+ case FB_TimestampTZ:
+ [self setExternalType:@"TIMESTAMP WITH TIME ZONE"];
+ [self setValueClassName:@"NSCalendarDate"];
+ break;
+
+ case FB_YearMonth:
+ [self setExternalType:@"INTERVAL YEAR TO MONTH"];
+ [self setValueClassName:@"NSNumber"];
+ break;
+ case FB_DayTime: /* NSDecimalNumber */
+ [self setExternalType:@"INTERVAL DAY TO SECOND"];
+ [self setValueClassName:@"NSNumber"];
+ break;
+
+ case FB_CLOB:
+ [self setExternalType:@"CLOB"];
+ [self setValueClassName:@"NSString"];
+ break;
+ case FB_BLOB:
+ [self setExternalType:@"BLOB"];
+ [self setValueClassName:@"NSData"];
+ break;
+
+ default:
+ [InvalidArgumentException raise:@"InvalidArgumentException"
+ format:
+ @"invalid frontbase type %d passed to -%s",
+ _type, NSStringFromSelector(_cmd)];
+ break;
+ }
+}
+
+@end
+
+void __link_EOAttributeFB() {
+ // used to force linking of object file
+ __link_EOAttributeFB();
+}
--- /dev/null
+/*
+ FBAdaptor+Types.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBAdaptor+Types.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#include "FrontBase2Adaptor.h"
+#include "FBChannel.h"
+#include "FBContext.h"
+
+@interface FrontBase2Adaptor(DomainResolver)
+- (BOOL)fetchDomainInfo;
+@end
+
+@implementation FrontBase2Adaptor(DomainResolver)
+
+typedef struct _InternalTypeMapping {
+ int code;
+ NSString *name;
+} InternalTypeMapping;
+
+static InternalTypeMapping internalTypeMappings[] = {
+ { FB_PrimaryKey, @"PRIMARYKEY" },
+ { FB_Boolean, @"BOOLEAN" },
+ { FB_Integer, @"INTEGER" },
+ { FB_SmallInteger, @"SMALLINT" },
+ { FB_Float, @"FLOAT" },
+ { FB_Real, @"REAL" },
+ { FB_Double, @"DOUBLE" },
+ { FB_Numeric, @"NUMERIC" },
+ { FB_Decimal, @"DECIMAL" },
+ { FB_Character, @"CHAR" },
+ { FB_VCharacter, @"VARCHAR" },
+ { FB_Bit, @"BIT" },
+ { FB_VBit, @"VARBIT" },
+ { FB_Date, @"DATE" },
+ { FB_Time, @"TIME" },
+ { FB_TimeTZ, @"TIME WITH TIME ZONE" },
+ { FB_Timestamp, @"TIMESTAMP" },
+ { FB_TimestampTZ, @"TIMESTAMP WITH TIME ZONE" },
+ { FB_YearMonth, @"INTERVAL YEAR TO MONTH" },
+ { FB_DayTime, @"INTERVAL DAY TO SECOND" },
+ { FB_CLOB, @"CLOB" },
+ { FB_BLOB, @"BLOB" },
+ { -1, nil } // end marker
+};
+
+static NSString *DomainQuery =
+ @"SELECT \"DOMAIN_NAME\" FROM INFORMATION_SCHEMA.domains";
+
+- (void)_resetTypeMapping {
+ if (self->typeNameToCode) {
+ NSFreeMapTable(self->typeNameToCode);
+ self->typeNameToCode = NULL;
+ }
+ if (self->typeCodeToName) {
+ NSFreeMapTable(self->typeCodeToName);
+ self->typeCodeToName = NULL;
+ }
+}
+
+- (void)_loadStandardTypes {
+ register InternalTypeMapping *mapping;
+
+ if (self->typeNameToCode == NULL) {
+ self->typeNameToCode = NSCreateMapTable(NSObjectMapKeyCallBacks,
+ NSIntMapValueCallBacks,
+ 64);
+ }
+ if (self->typeCodeToName == NULL) {
+ self->typeCodeToName = NSCreateMapTable(NSIntMapKeyCallBacks,
+ NSObjectMapValueCallBacks,
+ 64);
+ }
+
+ mapping = &(internalTypeMappings[1]);
+
+ while (mapping->name != nil) {
+ NSMapInsert(self->typeCodeToName,
+ (void *)(mapping->code),
+ (void *)mapping->name);
+ NSMapInsert(self->typeNameToCode,
+ (void *)mapping->name,
+ (void *)(mapping->code));
+ mapping++;
+ }
+}
+
+- (BOOL)fetchDomainInfo {
+ FrontBaseContext *ctx;
+ FrontBaseChannel *channel;
+ BOOL result;
+
+ if (self->typeNameToCode == NULL)
+ [self _loadStandardTypes];
+
+ result = NO;
+ ctx = (FrontBaseContext *)[self createAdaptorContext];
+ channel = (FrontBaseChannel *)[ctx createAdaptorChannel];
+
+ if ([channel openChannel]) {
+ if ([ctx beginTransaction]) {
+ if ([channel evaluateExpression:DomainQuery]) {
+ NSArray *attributes;
+ NSDictionary *record;
+ NSMutableArray *domains;
+
+ attributes = [channel describeResults];
+ domains = nil;
+
+ while ((record = [channel fetchAttributes:attributes withZone:NULL])) {
+ NSString *domainName;
+
+ if ((domainName = [record objectForKey:@"domainName"])) {
+ if (![domainName hasPrefix:@"T_"])
+ continue;
+
+ if (domains == nil)
+ domains = [NSMutableArray arrayWithCapacity:32];
+ [domains addObject:domainName];
+ }
+ else
+ NSLog(@"no domain name in record %@ ?", record);
+ }
+
+ /* no get the meta-info of the domains */
+
+ if ([domains count] > 0) {
+ /* we need to resolve domains, construct a VALUES expression .. */
+ NSMutableString *expr;
+ NSEnumerator *e;
+ NSString *domainName;
+ BOOL isFirst = YES;
+
+ expr = [NSMutableString stringWithCapacity:512];
+ [expr appendString:@"VALUES("];
+
+ e = [domains objectEnumerator];
+ while ((domainName = [e nextObject])) {
+ if (isFirst) isFirst = NO;
+ else [expr appendString:@","];
+
+ [expr appendString:@"CAST(NULL AS \""];
+ [expr appendString:domainName];
+ [expr appendString:@"\")"];
+ }
+
+ [expr appendString:@")"];
+
+ //NSLog(@"expr: %@", expr);
+
+ /* now execute expression */
+
+ if ([channel evaluateExpression:expr]) {
+ int *dc = channel->datatypeCodes;
+ int i;
+
+ for (i = 0; i < channel->numberOfColumns; i++) {
+ if (dc[i] > 0) {
+ NSString *domainName;
+
+ domainName = [[domains objectAtIndex:i] uppercaseString];
+
+ //NSMapInsert(self->typeCodeToName, (void *)dc[i], domainName);
+ NSMapInsert(self->typeNameToCode, domainName, (void *)dc[i]);
+#if 0
+ NSLog(@"domain %@ is code %i type %@",
+ domainName,
+ dc[i],
+ NSMapGet(self->typeCodeToName, (void*)dc[i]));
+#endif
+ }
+ }
+
+ [channel cancelFetch];
+
+ result = YES;
+ if (![ctx commitTransaction])
+ NSLog(@"couldn't common tx for domain-resolver ..");
+ }
+ else
+ NSLog(@"couldn't evaluate expression: %@", expr);
+ }
+ }
+ else
+ NSLog(@"couldn't evaluate expression: %@", DomainQuery);
+ if (!result) [ctx rollbackTransaction];
+ }
+ else
+ NSLog(@"couldn't begin tx for domain-resolver ..");
+
+ [channel closeChannel];
+ }
+ else
+ NSLog(@"couldn't open channel for domain-resolver ..");
+
+ return result;
+}
+
+@end
+
+@implementation FrontBase2Adaptor(ExternalTyping)
+
+- (int)typeCodeForExternalName:(NSString *)_typeName {
+ int code;
+
+ _typeName = [_typeName uppercaseString];
+
+ if (self->typeNameToCode == NULL)
+ [self fetchDomainInfo];
+
+ if (self->typeNameToCode == NULL)
+ return FB_VCharacter;
+
+ if ((code = (int)NSMapGet(self->typeNameToCode, _typeName)))
+ return code;
+
+ return FB_VCharacter;
+}
+
+- (NSString *)externalNameForTypeCode:(int)_typeCode {
+ if (_typeCode == 0)
+ return nil;
+
+ if (self->typeCodeToName == NULL)
+ [self fetchDomainInfo];
+
+ return NSMapGet(self->typeCodeToName, (void *)_typeCode);
+}
+
+- (BOOL)isInternalBlobType:(int)_type {
+ switch (_type) {
+ case FB_BLOB:
+ case FB_CLOB:
+ return YES;
+
+ default:
+ return NO;
+ }
+}
+
+- (BOOL)isBlobAttribute:(EOAttribute *)_attr {
+ int fbType;
+
+ NSAssert(_attr, @"missing attribute parameter");
+
+ fbType = [self typeCodeForExternalName:[_attr externalType]];
+
+ return [self isInternalBlobType:fbType];
+}
+
+- (BOOL)isValidQualifierType:(NSString *)_typeName {
+ switch ([self typeCodeForExternalName:_typeName]) {
+ case FB_BLOB:
+ case FB_CLOB:
+ return NO;
+
+ default:
+ return YES;
+ }
+}
+
+- (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
+ NSAssert(_attr, @"missing attribute parameter");
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ FBBlobHandle.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FrontBase Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBBlobHandle.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_FBBlobHandle_H___
+#define ___FB_FBBlobHandle_H___
+
+#import <Foundation/NSObject.h>
+#import "FBValues.h"
+
+@interface FBBlobHandle : NSObject < FBValues >
+{
+@private
+ NSString *bid;
+}
+
+- (id)initWithBlobID:(NSString *)_bid;
+- (NSString *)blobID;
+
+@end
+
+#endif /* ___FB_FBBlobHandle_H___ */
--- /dev/null
+// $Id: FBBlobHandle.m 1 2004-08-20 10:38:46Z znek $
+
+#include "FBBlobHandle.h"
+#include "FBValues.h"
+#include "common.h"
+
+@implementation FBBlobHandle
+
+- (id)initWithBlobID:(NSString *)_bid {
+ self->bid = [_bid copyWithZone:[self zone]];
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->bid);
+ [super dealloc];
+}
+
+/* accessors */
+
+- (NSString *)blobID {
+ return self->bid;
+}
+
+/* data */
+
++ (id)valueFromBytes:(const char *)_bytes length:(unsigned)_length
+ frontBaseType:(int)_fb attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel
+{
+ NSLog(@"called %@ on BLOB handle %@", NSStringFromSelector(_cmd), self);
+ return nil;
+}
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ NSLog(@"called %@ on BLOB handle %@", NSStringFromSelector(_cmd), self);
+ return nil;
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ switch (_type) {
+ case FB_Character:
+ case FB_VCharacter:
+ case FB_CLOB:
+ case FB_BLOB:
+ return self->bid;
+ //return [NSString stringWithFormat:@"@'%s'", [self->bid cString]];
+ }
+ return nil;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@[0x%08X]: id=%@>",
+ NSStringFromClass([self class]), self,
+ [self blobID]];
+}
+
+@end /* FBBlobHandle */
--- /dev/null
+/*
+ FBChannel+Model.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBChannel+Model.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_ModelFetching_H___
+#define ___FB_ModelFetching_H___
+
+#import "FBChannel.h"
+
+@class NSArray;
+@class EOModel;
+
+@interface FrontBaseChannel(ModelFetching)
+
+- (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames;
+- (NSArray *)describeTableNames;
+
+@end
+
+#endif
--- /dev/null
+/*
+ FBChannel+Model.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBChannel+Model.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import <GDLAccess/EOAccess.h>
+
+@interface EORelationship(Private)
+- (void)addJoin:(EOJoin *)_join;
+@end
+
+@implementation FrontBaseChannel(ModelFetching)
+
+- (NSArray *)_attributesForTableName:(NSString *)_tableName {
+ NSArray *attrForTableName = nil;
+
+ if ((attrForTableName =
+ [self->_attributesForTableName objectForKey:_tableName]) == nil) {
+ NSMutableArray *attributes = nil;
+ NSArray *resultDescription = nil;
+ NSString *selectExpression = nil;
+ NSString *columnNameKey = nil;
+ NSString *externalTypeKey = nil;
+ NSDictionary *row = nil;
+ unsigned cnt = 0;
+
+ selectExpression = [NSString stringWithFormat:
+ @"SELECT C1.\"COLUMN_NAME\", DTD1.\"DATA_TYPE\" FROM INFORMATION_SCHEMA."
+ @"COLUMNS C1, INFORMATION_SCHEMA.TABLES T1, INFORMATION_SCHEMA.DATA_"
+ @"TYPE_DESCRIPTOR DTD1 WHERE T1.\"TABLE_NAME\" = '%s' AND T1.\""
+ @"TABLE_PK\" = DTD1.\"TABLE_OR_DOMAIN_PK\" AND C1.\"TABLE_PK\" = T1."
+ @"\"TABLE_PK\" AND C1.\"COLUMN_PK\" = DTD1.\"COLUMN_NAME_PK\"",
+ [[_tableName uppercaseString] cString]];
+
+ if (![self evaluateExpression:selectExpression]) {
+ fprintf(stderr, "Couldn`t evaluate expression %s\n",
+ [selectExpression cString]);
+ return nil;
+ }
+ resultDescription = [self describeResults];
+ columnNameKey = [(EOAttribute *)[resultDescription objectAtIndex:0] name];
+ externalTypeKey = [(EOAttribute *)[resultDescription objectAtIndex:1] name];
+ attributes = [NSMutableArray arrayWithCapacity:16];
+
+ while ((row = [self fetchAttributes:resultDescription withZone:NULL])) {
+ EOAttribute *attribute = nil;
+ NSString *columnName = nil;
+ NSString *externalType = nil;
+ NSString *attrName = nil;
+ int fbType = 0;
+
+ attribute = [[EOAttribute alloc] init];
+ columnName = [row objectForKey:columnNameKey];
+ externalType = [row objectForKey:externalTypeKey];
+ attrName = [columnName _sybModelMakeInstanceVarName];
+ fbType = [(id)[adaptorContext adaptor]
+ typeCodeForExternalName:externalType];
+
+ [attribute setName:attrName];
+ [attribute setColumnName:columnName];
+ [attribute loadValueClassAndTypeFromFrontBaseType:fbType];
+ [attribute setExternalType:externalType];
+
+ [attributes addObject:attribute];
+ RELEASE(attribute); attribute = nil;
+ }
+
+ // fetch external types
+
+ for (cnt = 0; cnt < [attributes count]; cnt++) {
+ EOAttribute *attribute = nil;
+ NSString *externalType = nil;
+ int fbType = 0;
+
+ attribute = [attributes objectAtIndex:cnt];
+ externalType = [attribute externalType];
+ fbType = [(id)[adaptorContext adaptor]
+ typeCodeForExternalName:externalType];
+ [attribute loadValueClassAndTypeFromFrontBaseType:fbType];
+ [attribute setExternalType:externalType];
+ }
+ attrForTableName = attributes;
+ [self->_attributesForTableName setObject:attrForTableName forKey:_tableName];
+ }
+ return attrForTableName;
+}
+
+- (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName {
+ NSArray *pkNameForTable = nil;
+
+ if (_tableName == nil)
+ return nil;
+
+ if ((pkNameForTable =
+ [self->_primaryKeysNamesForTableName objectForKey:_tableName]) == nil) {
+ NSMutableArray *primaryKeys = nil;
+ NSString *selectExpression = nil;
+ NSArray *resultDescription = nil;
+ NSString *columnNameKey = nil;
+ NSDictionary *row = nil;
+
+ selectExpression = [NSString stringWithFormat:
+ @"SELECT C1.\"COLUMN_NAME\" FROM INFORMATION_SCHEMA.COLUMNS C1, "
+ @"INFORMATION_SCHEMA.TABLES T1, INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC1, "
+ @"INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1 WHERE T1.\"TABLE_NAME\" = "
+ @"'%s' AND TC1.\"TABLE_PK\" = T1.\"TABLE_PK\" AND TC1.\"CONSTRAINT"
+ @"_TYPE\" = 'PRIMARY KEY' AND KCU1.\"TABLE_PK\" = T1.\"TABLE_PK\" AND "
+ @"KCU1.\"CONSTRAINT_NAME_PK\" = TC1.\"CONSTRAINT_NAME_PK\" AND C1.\""
+ @"COLUMN_PK\" = KCU1.\"COLUMN_PK\"",
+ [[_tableName uppercaseString] cString]];
+
+ if (![self evaluateExpression:selectExpression]) {
+ fprintf(stderr, "Couldn`t evaluate expression %s\n",
+ [selectExpression cString]);
+ return nil;
+ }
+ resultDescription = [self describeResults];
+ columnNameKey = [(EOAttribute *)[resultDescription objectAtIndex:0]
+ name];
+ primaryKeys = [NSMutableArray arrayWithCapacity:4];
+
+ while ((row = [self fetchAttributes:resultDescription withZone:NULL]))
+ [primaryKeys addObject:[row objectForKey:columnNameKey]];
+
+ pkNameForTable = primaryKeys;
+ [self->_primaryKeysNamesForTableName setObject:pkNameForTable
+ forKey:_tableName];
+ }
+ return pkNameForTable;
+}
+
+- (NSArray *)_foreignKeysForTableName:(NSString *)_tableName {
+ return [NSArray array];
+}
+
+- (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames {
+ NSMutableArray *buildRelShips = nil;
+ EOModel *model = nil;
+ int cnt = 0;
+ int tc = 0;
+
+ buildRelShips = [NSMutableArray arrayWithCapacity:64];
+ model = [[EOModel alloc] init];
+ tc = [_tableNames count];
+ AUTORELEASE(model);
+
+ for (cnt = 0; cnt < tc; cnt++) {
+ NSMutableDictionary *relNamesUsed = nil;
+ NSMutableArray *classProperties = nil;
+ NSMutableArray *primaryKeyAttributes = nil;
+ NSString *tableName = nil;
+ NSArray *attributes = nil;
+ NSArray *pkeys = nil;
+ NSArray *fkeys = nil;
+ EOEntity *entity = nil;
+ int cnt2 = 0;
+ int ac = 0;
+ int fkc = 0;
+
+ relNamesUsed = [NSMutableDictionary dictionary];
+ classProperties = [NSMutableArray array];
+ primaryKeyAttributes = [NSMutableArray array];
+ tableName = [_tableNames objectAtIndex:cnt];
+ attributes = [self _attributesForTableName:tableName];
+ pkeys = [self _primaryKeysNamesForTableName:tableName];
+ fkeys = [self _foreignKeysForTableName:tableName];
+ entity = [[EOEntity alloc] init];
+ ac = [attributes count];
+ fkc = [fkeys count];
+ AUTORELEASE(entity);
+
+ [entity setName:[tableName _sybModelMakeClassName]];
+ [entity setClassName:
+ [@"EO" stringByAppendingString:[tableName _sybModelMakeClassName]]];
+ [entity setExternalName:tableName];
+ [classProperties addObjectsFromArray:[entity classProperties]];
+ [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]];
+ [model addEntity:entity];
+
+ for (cnt2 = 0; cnt2 < ac; cnt2++) {
+ EOAttribute *attribute = [attributes objectAtIndex:cnt2];
+ NSString *columnName = [attribute columnName];
+
+ [entity addAttribute:attribute];
+ [classProperties addObject:attribute];
+
+ if ([pkeys containsObject:columnName])
+ [primaryKeyAttributes addObject:attribute];
+ }
+ [entity setClassProperties:classProperties];
+ [entity setPrimaryKeyAttributes:primaryKeyAttributes];
+
+ for (cnt2 = 0; cnt2 < fkc; cnt2++) {
+ NSDictionary *fkey = nil;
+ NSMutableArray *classProperties = nil;
+ NSString *sa = nil;
+ NSString *da = nil;
+ NSString *dt = nil;
+ EORelationship *rel = nil;
+ EOJoin *join = nil;
+ NSString *relName = nil;
+
+ fkey = [fkeys objectAtIndex:cnt2];
+ classProperties = [NSMutableArray array];
+ sa = [fkey objectForKey:@"sourceAttr"];
+ da = [fkey objectForKey:@"targetAttr"];
+ dt = [fkey objectForKey:@"targetTable"];
+ rel = [[EORelationship alloc] init];
+ join = [[EOJoin alloc] init];
+ AUTORELEASE(rel);
+ AUTORELEASE((id)join);
+
+ if ([pkeys containsObject:sa])
+ relName = [@"to" stringByAppendingString:[dt _sybModelMakeClassName]];
+ else {
+ relName = [@"to" stringByAppendingString:
+ [[sa _sybModelMakeInstanceVarName]
+ _sybStringWithCapitalizedFirstChar]];
+ if ([relName hasSuffix:@"Id"]) {
+ int cLength = [relName cStringLength];
+
+ relName = [relName substringToIndex:cLength - 2];
+ }
+ }
+ if ([relNamesUsed objectForKey:relName]) {
+ int useCount = [[relNamesUsed objectForKey:relName] intValue];
+
+ [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)]
+ forKey:relName];
+ relName = [NSString stringWithFormat:@"%s%d",
+ [relName cString], useCount];
+ }
+ else
+ [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName];
+
+ [rel setName:relName];
+ //[rel setDestinationEntity:(EOEntity *)[dt _sybModelMakeClassName]];
+ [rel setToMany:NO];
+
+ [(id)join setSourceAttribute:
+ (EOAttribute *)[sa _sybModelMakeInstanceVarName]];
+ [(id)join setDestinationAttribute:
+ (EOAttribute *)[da _sybModelMakeInstanceVarName]];
+ [rel addJoin:join];
+
+ [entity addRelationship:rel];
+ [classProperties addObjectsFromArray:[entity classProperties]];
+ [classProperties addObject:rel];
+ [entity setClassProperties:classProperties];
+ [buildRelShips addObject:rel];
+ }
+
+ [entity setAttributesUsedForLocking:[[entity attributes] copy]];
+ }
+
+ [buildRelShips makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
+
+ [model setAdaptorName:@"FrontBase2"];
+ [model setAdaptorClassName:@"FrontBase2Adaptor"];
+ [model setConnectionDictionary:[[adaptorContext adaptor] connectionDictionary]];
+ return model;
+}
+
+- (NSArray *)describeTableNames {
+ NSMutableArray *tableNames = nil;
+ NSArray *resultDescription = nil;
+ NSString *attributeName = nil;
+ NSDictionary *row = nil;
+ NSString *selectExpression = nil;
+
+ selectExpression = @"SELECT T1.\"TABLE_NAME\" FROM "
+ @"INFORMATION_SCHEMA.TABLES T1";
+
+ if (![self evaluateExpression:selectExpression]) {
+ fprintf(stderr, "Couldn`t evaluate expression %s\n",
+ [selectExpression cString]);
+ return nil;
+ }
+ resultDescription = [self describeResults];
+ attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name];
+ tableNames = [NSMutableArray arrayWithCapacity:16];
+
+ while ((row = [self fetchAttributes:resultDescription withZone:NULL]))
+ [tableNames addObject:[row objectForKey:attributeName]];
+
+ return tableNames;
+}
+
+@end
+
+void __link_FBChannelModel() {
+ // used to force linking of object file
+ __link_FBChannelModel();
+}
--- /dev/null
+/*
+ FBChannel.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBChannel.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_Channel_H___
+#define ___FB_Channel_H___
+
+#import <GDLAccess/EOAdaptorChannel.h>
+#import "FBHeaders.h"
+
+@class NSArray, NSString, NSMutableDictionary;
+
+struct _FBColumnData;
+
+@interface FrontBaseChannel : EOAdaptorChannel
+{
+@public
+ /* connection is valid after an openChannel call */
+ FBCDatabaseConnection *fbdc;
+ void **rawRows;
+ FBCRowHandler *rowHandler;
+ FBCMetaData *cmdMetaData;
+ char *fetchHandle;
+ BOOL isFirstInBatch;
+
+ /* these variables are valid only during an evaluation */
+ int currentRow;
+ int numberOfColumns; // number of columns in result set
+ int *datatypeCodes;
+ int rowsAffected;
+ unsigned txVersion;
+ NSArray *selectedAttributes; // contains the real select order
+
+ /* turns on/off channel debugging */
+ BOOL isDebuggingEnabled;
+ NSString *sqlLogFile;
+
+ /* caching */
+ NSMutableDictionary *_primaryKeysNamesForTableName;
+ NSMutableDictionary *_attributesForTableName;
+}
+
+- (void)setDebugEnabled:(BOOL)_flag;
+- (BOOL)isDebugEnabled;
+
+- (BOOL)isOpen;
+- (BOOL)openChannel;
+- (void)closeChannel;
+- (void)primaryCloseChannel; // private
+
+- (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes
+ withZone:(NSZone *)_zone;
+
+- (BOOL)evaluateExpression:(NSString *)_expression;
+
+// cancelFetch is always called to terminate a fetch
+// (even by primaryFetchAttributes)
+// it frees all fetch-local variables
+- (void)cancelFetch;
+
+// uses type information to create EOAttribute objects
+- (NSArray *)describeResults;
+
+@end
+
+#endif
--- /dev/null
+/*
+ FBChannel.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBChannel.m 1 2004-08-20 10:38:46Z znek $
+
+#include <ctype.h>
+#include <string.h>
+#if HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#import "common.h"
+#include "FBBlobHandle.h"
+#include <NGExtensions/NSString+misc.h>
+
+#include <FBCAccess/FBCDigestPassword.h>
+#include <GDLAccess/EORecordDictionary.h>
+#import <EOControl/EOSortOrdering.h>
+
+//#define BLOB_DEBUG 1
+
+@implementation FrontBaseChannel
+
+static EONull *null = nil;
+
++ (void)initialize {
+ if (null == NULL) null = [[EONull null] retain];
+}
+
+#ifdef __MINGW32__
+extern __declspec(import) void fbcInitialize(void);
+#endif
+
+- (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext {
+ static BOOL didInit = NO;
+ if (!didInit) {
+ didInit = YES;
+#ifdef __MINGW32__
+ fbcInitialize();
+#endif
+#ifdef __APPLE__
+ fbcInitialize();
+#endif
+ }
+
+ if ((self = [super initWithAdaptorContext:_adaptorContext])) {
+ [self setDebugEnabled:[[NSUserDefaults standardUserDefaults]
+ boolForKey:@"FBDebugEnabled"]];
+ sqlLogFile = [[[NSUserDefaults standardUserDefaults]
+ stringForKey:@"FBLogFile"]
+ copyWithZone:[self zone]];
+ self->_primaryKeysNamesForTableName = [[NSMutableDictionary alloc] init];
+ self->_attributesForTableName = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+#if !LIB_FOUNDATION_BOEHM_GC
+- (void)dealloc {
+ if ([self isOpen]) {
+ [self cancelFetch];
+ [self closeChannel];
+ }
+ RELEASE(self->sqlLogFile);
+ RELEASE(self->_primaryKeysNamesForTableName);
+ RELEASE(self->_attributesForTableName);
+ [super dealloc];
+}
+#endif
+
+// NSCopying methods
+
+- (id)copyWithZone:(NSZone *)zone {
+ return RETAIN(self);// copy is needed during creation of NSNotification object
+}
+
+// debugging
+
+- (void)setDebugEnabled:(BOOL)_flag {
+ self->isDebuggingEnabled = _flag;
+}
+- (BOOL)isDebugEnabled {
+ return self->isDebuggingEnabled;
+}
+
+// open/close
+
+- (BOOL)isOpen {
+ return self->fbdc != NULL ? YES : NO;
+}
+
+- (BOOL)openChannel {
+ FrontBase2Adaptor *adaptor;
+ FBCMetaData *md;
+ BOOL result = NO;
+ NSString *txIsoLevel;
+ NSString *locking;
+ NSString *expr;
+ const char *password;
+ char pwdDigest[17];
+
+ // [self setDebugEnabled:YES];
+
+ adaptor = (FrontBase2Adaptor *)[[self adaptorContext] adaptor];
+
+ if (![super openChannel])
+ return NO;
+
+ /* digest the database password */
+
+ if ((password = [[adaptor databasePassword] cString])) {
+ if (fbcDigestPassword("_SYSTEM", (char *)password, pwdDigest) == NULL) {
+ NSLog(@"%@: Couldn't digest password !", self);
+ pwdDigest[0] = '\0';
+ }
+ }
+ else
+ pwdDigest[0] = '\0';
+
+ /* connect to database */
+
+ if (isDebuggingEnabled)
+ NSLog(@"Open fb-channel[%p]: db=%@, server=%@", self,
+ [adaptor databaseName], [adaptor serverName]);
+
+ self->fbdc =
+ fbcdcConnectToDatabase((char *)[[adaptor databaseName] cString],
+ (char *)[[adaptor serverName] cString],
+ (char *)pwdDigest);
+ if (self->fbdc == NULL) {
+ if (isDebuggingEnabled) {
+ NSLog(@"FrontBase channel 0x%08X (db=%@, server=%@, digest=%s) "
+ @"could not be opened: %s ..", self,
+ [adaptor databaseName], [adaptor serverName],
+ pwdDigest /* ? "yes" : "no"*/,
+ fbcdcClassErrorMessage());
+ }
+ return NO;
+ }
+
+ fbcdcSetRollbackAfterError(self->fbdc, True);
+
+ /* digest the user password */
+#if 0
+ if ((password = [[adaptor loginPassword] cString])) {
+ if (fbcDigestPassword((char *)[[adaptor loginName] cString],
+ (char *)password, pwdDigest) == NULL) {
+ NSLog(@"%@: Couldn't digest password !", self);
+ pwdDigest[0] = '\0';
+ }
+ }
+ else
+ pwdDigest[0] = '\0';
+#else
+ if (!(password = [[adaptor loginPassword] cString]))
+ password = "\0";
+#endif
+
+ /* create session */
+
+ md = fbcdcCreateSession(self->fbdc,
+ (char *)[[NSString stringWithFormat:
+ @"GDL<0x%08X>", self]
+ cString],
+ (char *)[[adaptor loginName] cString],
+ // pwdDigest,
+ (char *)password,
+ (char *)[NSUserName() cString]);
+ if (md == NULL) {
+ if (isDebuggingEnabled) {
+ NSLog(@"FrontBase session (channel=0x%08X) couldn't be created, "
+ @" login=%@ password=%s user=%@: %s.",
+ self,
+ [adaptor loginName], [adaptor loginPassword],
+ [adaptor loginName],
+ fbcdcClassErrorMessage());
+ }
+ fbcdcClose(self->fbdc); self->fbdc = NULL;
+ return NO;
+ }
+
+ if (fbcmdErrorCount(md) > 0) {
+ if (isDebuggingEnabled) {
+ FBCErrorMetaData *emd;
+ int i, count;
+
+ emd = fbcdcErrorMetaData(self->fbdc, md);
+
+ NSLog(@"FrontBase session (channel=0x%08X) couldn't be created:", self);
+
+ for (i = 0, count = fbcemdErrorCount(emd); i < count; i++) {
+ unsigned code;
+ const char *errorKind;
+ const char *emsg;
+
+ code = fbcemdErrorCodeAtIndex(emd, i);
+ errorKind = fbcemdErrorKindAtIndex(emd, i);
+ emsg = fbcemdErrorMessageAtIndex(emd, i);
+
+ NSLog(@" code=%i", code);
+ NSLog(@" kind=%s", errorKind);
+ NSLog(@" msdg=%s", emsg);
+#if 0
+ free((void *)errorKind);
+#endif
+ free((void *)emsg);
+ }
+ fbcemdRelease(emd); emd = NULL;
+ }
+ fbcdcClose(self->fbdc); self->fbdc = NULL;
+ fbcmdRelease(md); md = NULL;
+ return NO;
+ }
+
+ fbcmdRelease(md); md = NULL;
+
+ result = YES;
+
+ /* apply session level setting (locking & tx levels) */
+
+ if ((txIsoLevel = [adaptor transactionIsolationLevel]) == nil)
+ txIsoLevel = @"READ COMMITTED";
+ if ((locking = [adaptor lockingDiscipline]) == nil)
+ locking = @"OPTIMISTIC";
+
+ expr = [NSString stringWithFormat:
+ @"SET TRANSACTION ISOLATION LEVEL %s, LOCKING %s",
+ [txIsoLevel cString], [locking cString]];
+ if (![self evaluateExpression:expr]) {
+ if (isDebuggingEnabled)
+ NSLog(@"%@: couldn't apply tx iso level '%@' and locking '%@'..",
+ self, txIsoLevel, locking);
+ }
+
+#if LIB_FOUNDATION_BOEHM_GC
+ [GarbageCollector registerForFinalizationObserver:self
+ selector:@selector(_adaptorWillFinalize:)
+ object:[[self adaptorContext] adaptor]];
+#endif
+
+ if (isDebuggingEnabled)
+ NSLog(@"FrontBase channel 0x%08X opened ..", self);
+
+ return result;
+}
+
+- (void)primaryCloseChannel {
+ /* release all resources */
+
+ if (self->fbdc) {
+ if (isDebuggingEnabled) {
+ id ad;
+
+ ad = [[self adaptorContext] adaptor];
+ NSLog(@"Close fb-channel[%p]: db=%@, server=%@", self,
+ ad, [ad serverName]);
+ }
+
+ fbcdcClose(self->fbdc);
+ self->fbdc = NULL;
+ }
+
+ RELEASE(self->selectedAttributes); self->selectedAttributes = nil;
+}
+
+- (void)closeChannel {
+ [super closeChannel];
+ [self primaryCloseChannel];
+}
+
+// fetching rows
+
+- (void)cancelFetch {
+ if (![self isOpen]) {
+ [FrontBaseException raise:@"ChannelNotOpenException"
+ format:@"No fetch in progress, fb connection is not"
+ @" open (channel=%@)", self];
+ }
+
+ if (self->fetchHandle) {
+ FBCMetaData *md;
+ if ((md = fbcdcCancelFetch(self->fbdc, self->fetchHandle))) {
+ fbcmdRelease(md); md = NULL;
+ }
+ self->fetchHandle = NULL;
+ }
+
+ if (self->datatypeCodes) {
+ free(self->datatypeCodes);
+ self->datatypeCodes = NULL;
+ }
+
+ if (self->rowHandler) {
+ fbcrhRelease(self->rowHandler);
+ self->rowHandler = NULL;
+ self->rawRows = NULL;
+ }
+ else {
+ NSAssert(self->rawRows == NULL, @"raw rows set, but no row handler ! ..");
+ }
+
+ if (self->cmdMetaData) {
+ fbcmdRelease(self->cmdMetaData);
+ self->cmdMetaData = NULL;
+ }
+
+ NSAssert(self->rowHandler == NULL, @"row handler still set ..");
+ NSAssert(self->rawRows == NULL, @"raw row still set ..");
+
+ [super cancelFetch];
+
+ self->currentRow = 0;
+ self->numberOfColumns = 0;
+ RELEASE(self->selectedAttributes); self->selectedAttributes = nil;
+}
+
+- (NSArray *)describeResults {
+ int cnt;
+ NSMutableArray *result = nil;
+ NSMutableDictionary *usedNames = nil;
+ NSNumber *yesObj = [NSNumber numberWithBool:YES];
+
+ if (![self isFetchInProgress]) {
+ [FrontBaseException raise:@"NoFetchInProgress"
+ format:@"No fetch in progress (channel=%@)", self];
+ }
+
+ NSAssert(self->cmdMetaData, @"no cmd-meta-data ..");
+
+ result =
+ [[NSMutableArray alloc] initWithCapacity:self->numberOfColumns + 1];
+ usedNames =
+ [[NSMutableDictionary alloc] initWithCapacity:self->numberOfColumns + 1];
+
+ for (cnt = 0; cnt < self->numberOfColumns; cnt++) {
+ const FBCColumnMetaData *cmd;
+ EOAttribute *attribute = nil;
+ NSString *columnName = nil;
+ NSString *attrName = nil;
+
+ cmd = fbcmdColumnMetaDataAtIndex(self->cmdMetaData, cnt);
+
+ if (cmd) {
+ const char *s;
+
+ if ((s = fbccmdLabelName(cmd)))
+ columnName = [NSString stringWithCString:s];
+ else if ((s = fbccmdColumnName(cmd)))
+ columnName = [NSString stringWithCString:s];
+ }
+
+ if ([columnName length] == 0) {
+ columnName = [NSString stringWithFormat:@"column%i", cnt];
+ attrName = [NSString stringWithFormat:@"column%i", cnt];
+ }
+ else
+ attrName = [columnName _sybModelMakeInstanceVarName];
+
+ if ([[usedNames objectForKey:attrName] boolValue]) {
+ int cnt2 = 0;
+ char buf[64];
+ NSString *newAttrName = nil;
+
+ for (cnt2 = 2; cnt2 < 100; cnt2++) {
+ sprintf(buf, "%i", cnt2);
+
+ newAttrName = [attrName stringByAppendingString:
+ [NSString stringWithCString:buf]];
+
+ if (![[usedNames objectForKey:newAttrName] boolValue]) {
+ attrName = newAttrName;
+ break;
+ }
+ }
+ }
+ [usedNames setObject:yesObj forKey:attrName];
+
+ attribute = [[EOAttribute alloc] init];
+ [attribute setName:attrName];
+ [attribute setColumnName:columnName];
+ [attribute loadValueClassAndTypeFromFrontBaseType:self->datatypeCodes[cnt]];
+ [result addObject:attribute];
+ RELEASE(attribute); attribute = nil;
+ }
+
+ RELEASE(usedNames);
+ usedNames = nil;
+
+ return AUTORELEASE(result);
+}
+
+- (int)batchSize {
+ return 1000;
+}
+
+- (BOOL)_nextBatch {
+ if (self->rowHandler) {
+ fbcrhRelease(self->rowHandler);
+ self->rowHandler = NULL;
+ self->rawRows = NULL;
+ }
+
+ //NSLog(@"fetching new batch ..");
+ NSAssert(self->fetchHandle, @"missing fetch handle ..");
+ self->rawRows = fbcdcFetch(self->fbdc, [self batchSize], self->fetchHandle);
+
+ if (self->rawRows) {
+ self->rowHandler = fbcrhInitWith(self->rawRows, self->cmdMetaData);
+ self->isFirstInBatch = YES;
+ //NSLog(@"fetched new batch %i rows ..", fbcrhRowCount(self->rowHandler));
+ }
+ else {
+ /* no more fetch data, finish fetch op */
+ [self cancelFetch];
+ self->isFetchInProgress = NO;
+ return NO;
+ }
+
+ return YES;
+}
+
+- (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes
+ withZone:(NSZone *)_zone
+{
+ NSMutableDictionary *record;
+ void **rawRow;
+ int i;
+
+ record = nil;
+
+ if (!self->isFetchInProgress)
+ return nil;
+
+ if (self->rawRows == NULL) {
+ if (![self _nextBatch])
+ return nil;
+ }
+
+ if (self->selectedAttributes == nil) {
+ self->selectedAttributes = RETAIN([self describeResults]);
+ }
+
+ if ([_attributes count] < [self->selectedAttributes count])
+ _attributes = self->selectedAttributes;
+
+ NSAssert(self->rowHandler, @"missing row handler ..");
+
+ rawRow = self->isFirstInBatch
+ ? fbcrhFirstRow(self->rowHandler)
+ : fbcrhNextRow(self->rowHandler);
+
+ if (rawRow == NULL) {
+ /* no more rows available in fetch-buffer, get next batch */
+ if (![self _nextBatch])
+ return nil;
+
+ rawRow = self->isFirstInBatch
+ ? fbcrhFirstRow(self->rowHandler)
+ : fbcrhNextRow(self->rowHandler);
+ }
+ self->isFirstInBatch = NO;
+
+ if (rawRow == NULL) {
+ /* no rows were in batch and no new batch could be fetched, so we finished */
+ [self cancelFetch];
+ self->isFetchInProgress = NO;
+ return nil;
+ }
+
+ /* deconstruct raw row */
+
+ {
+ id objects[self->numberOfColumns];
+ id keys[self->numberOfColumns];
+
+ for (i = 0; i < self->numberOfColumns; i++) {
+ EOAttribute *attribute;
+ register void *rawValue;
+ Class valueClass;
+ NSString *attrName;
+ id value;
+
+ objects[i] = NULL;
+ keys[i] = NULL;
+
+ if (self->datatypeCodes[i] < 1)
+ continue;
+
+#if 1
+ if (!(attribute = [_attributes objectAtIndex:i])) {
+ attribute = [self->selectedAttributes objectAtIndex:i];
+ }
+#endif
+
+ attrName = [attribute name];
+ valueClass = NSClassFromString([attribute valueClassName]);
+
+#if DEBUG
+ NSAssert3(valueClass,
+ @"no valueClass for attribute %@ entity %@ name %@ ..",
+ attribute, [attribute entity], [attribute valueClassName]);
+#endif
+
+ if (attrName == nil)
+ attrName = [NSString stringWithFormat:@"column%i", i];
+
+ rawValue = rawRow[i];
+ if (rawValue == NULL) {
+ value = null;
+ }
+ else {
+ FBCBlobHandle *handle = NULL;
+ unsigned int len = 4;
+
+ switch (self->datatypeCodes[i]) {
+ case FB_Boolean:
+ len = sizeof(unsigned char);
+ break;
+
+ case FB_Character:
+ len = strlen(rawValue);
+ break;
+ case FB_VCharacter:
+ len = strlen(rawValue);
+ break;
+ case FB_Date:
+ NSLog(@"handling date ..");
+ len = strlen(rawValue);
+ break;
+ case FB_Timestamp:
+ NSLog(@"handling timestamp ..");
+ len = strlen(rawValue);
+ break;
+ case FB_TimestampTZ:
+ len = strlen(rawValue);
+ if (len != 25) {
+ NSLog(@"handling timestamp with TZ with length=%i ..", len);
+ }
+ break;
+
+ case FB_SmallInteger:
+ len = sizeof(short);
+ break;
+
+ case FB_Integer:
+ case FB_YearMonth:
+ len = sizeof(int);
+ break;
+
+ case FB_Double:
+ case FB_Real:
+ case FB_Numeric:
+ case FB_Decimal:
+ case FB_DayTime:
+ len = sizeof(double);
+ break;
+
+ case FB_Float:
+ len = sizeof(float);
+ break;
+
+ case FB_CLOB:
+ case FB_BLOB:
+ /*
+ CLOB/BLOB are a bit more tricky, mainly because values of up to a
+ given size are inlined in the fetch result, i.e. no need for a
+ round trip to the server.
+ */
+ if ((*(unsigned char *)rawValue) == 0) {
+ /* blob via handle */
+#if BLOB_DEBUG
+ NSLog(@"blob via handle %s",
+ ((FBCBlobIndirect *)rawValue)->handleAsString);
+#endif
+
+ handle =
+ fbcbhInitWithHandle(((FBCBlobIndirect *)rawValue)->handleAsString);
+ len = fbcbhBlobSize(handle);
+
+ rawValue = fbcdcReadBLOB(self->fbdc, handle);
+ }
+ else {
+ /* blob inline */
+ FBCBlobDirect *blob;
+
+#if BLOB_DEBUG
+ NSLog(@"blob inline");
+#endif
+ blob = rawValue;
+ rawValue = blob->blobData;
+ len = blob->blobSize;
+ }
+#if BLOB_DEBUG
+ NSLog(@" size=%d", len);
+#endif
+ break;
+ }
+
+ /* make an object value from the data */
+
+#if DEBUG
+ NSAssert3(valueClass,
+ @"lost valueClass for attribute %@ entity %@ name %@ ..",
+ attribute, [attribute entity], [attribute valueClassName]);
+#endif
+
+ value = [valueClass valueFromBytes:rawValue length:len
+ frontBaseType:self->datatypeCodes[i]
+ attribute:attribute
+ adaptorChannel:self];
+
+#if DEBUG
+ if (value == nil) {
+ NSAssert4(value,
+ @"no value for attribute %@ entity %@ "
+ @"valueClass %@, record %@ ..",
+ attribute, [attribute entity],
+ NSStringFromClass(valueClass), record);
+ }
+#endif
+
+ /* free BLOB handle if one was allocated */
+
+ if (handle) {
+ fbcbhRelease(handle);
+ handle = NULL;
+ }
+ }
+
+#if DEBUG
+ NSAssert2(value, @"no value for attribute %@ entity %@ ..",
+ attribute, [attribute entity]);
+#endif
+
+ objects[i] = value;
+ keys[i] = [attribute name];
+ }
+ {
+ static Class EORecordDictionaryClass = nil;
+
+ if (EORecordDictionaryClass == nil)
+ EORecordDictionaryClass = [EORecordDictionary class];
+
+ record = (id)NSAllocateObject(EORecordDictionaryClass,
+ sizeof(EORecordDictionary) *
+ self->numberOfColumns, nil);
+ record = [record initWithObjects:objects forKeys:keys
+ count:self->numberOfColumns];
+ AUTORELEASE(record);
+ }
+ }
+ return record;
+}
+
+/* sending sql to server */
+
+- (BOOL)evaluateExpression:(NSString *)_expression {
+ BOOL result;
+#if DEBUG
+ static Class NSDateClass = Nil;
+ NSDate *startDate;
+#endif
+
+ *(&result) = YES;
+ NSAssert(self->rowHandler == NULL, @"raw handler still available ..");
+ NSAssert(self->rawRows == NULL, @"raw rows still available ..");
+ NSAssert(self->fetchHandle == NULL, @"fetch handle still available ..");
+
+ if (_expression == nil) {
+ [InvalidArgumentException raise:@"InvalidArgumentException"
+ format:@"parameter for evaluateExpression: "
+ @"must not be null (channel=%@)", self];
+ }
+
+ *(&_expression) = AUTORELEASE([_expression mutableCopy]);
+
+ if (delegateRespondsTo.willEvaluateExpression) {
+ EODelegateResponse response =
+ [delegate adaptorChannel:self
+ willEvaluateExpression:(NSMutableString *)_expression];
+
+ if (response == EODelegateRejects)
+ return NO;
+ else if (response == EODelegateOverrides)
+ return YES;
+ }
+
+ if (isDebuggingEnabled)
+ NSLog(@"SQL[%p]: %@", self, _expression);
+
+
+ if (![self isOpen]) {
+ [FrontBaseException raise:@"ChannelNotOpenException"
+ format:@"FrontBase connection is not open (channel=%@)",
+ self];
+ }
+ if (self->cmdMetaData != NULL) {
+ [FrontBaseException raise:@"CommandInProgressException"
+ format:@"command data already set up"
+ @" (channel=%@)", self];
+ }
+
+ _expression = [_expression stringByAppendingString:@";"];
+
+ if (self->sqlLogFile) {
+ FILE *fh;
+ if ((fh = fopen([self->sqlLogFile cString], "a"))) {
+ fprintf(fh, "%s\n", [_expression cString]);
+ fflush(fh);
+ fclose(fh);
+ }
+ }
+
+ /* execute expression */
+
+#if DEBUG
+ if (NSDateClass == Nil) NSDateClass = [NSDate class];
+ startDate = [NSDateClass date];
+#endif
+
+ self->cmdMetaData = fbcdcExecuteDirectSQL(self->fbdc,
+ (char *)[_expression cString]);
+ if (self->cmdMetaData == NULL) {
+ NSLog(@"%@: could not execute SQL: %@", self, _expression);
+ return NO;
+ }
+
+ /* check for errors */
+
+ if (fbcmdErrorCount(self->cmdMetaData) > 0) {
+ FBCErrorMetaData *emd;
+ char *msg;
+ NSString *error;
+ int i, count;
+
+ emd = fbcdcErrorMetaData(self->fbdc, self->cmdMetaData);
+
+ for (i = 0, count = fbcemdErrorCount(emd); i < count; i++) {
+ unsigned code;
+ const char *errorKind;
+ const char *emsg;
+
+ code = fbcemdErrorCodeAtIndex(emd, i);
+ errorKind = fbcemdErrorKindAtIndex(emd, i);
+ emsg = fbcemdErrorMessageAtIndex(emd, i);
+
+ NSLog(@" code=%i", code);
+ NSLog(@" kind=%s", errorKind);
+ NSLog(@" msdg=%s", emsg);
+#if 0
+ free((void *)errorKind);
+#endif
+ free((void *)emsg);
+ }
+
+ if ((msg = fbcemdAllErrorMessages(emd)))
+ error = [NSString stringWithCString:msg];
+ else
+ error = @"unknown";
+ free(msg); msg = NULL;
+ fbcemdRelease(emd); emd = NULL;
+ fbcmdRelease(self->cmdMetaData); self->cmdMetaData = NULL;
+
+ if (self->sqlLogFile) {
+ FILE *fh;
+ if ((fh = fopen([self->sqlLogFile cString], "a"))) {
+ fprintf(fh, "# failed: %s\n",
+ [[error stringByApplyingCEscaping] cString]);
+ fflush(fh);
+ fclose(fh);
+ }
+ }
+
+ NSLog(@"%@: could not execute SQL: %@\n reason: %@",
+ self, _expression,
+ error);
+ return NO;
+ }
+
+ /* init common results */
+
+ NSAssert(self->cmdMetaData, @"missing command-meta-data");
+ self->numberOfColumns = fbcmdColumnCount(self->cmdMetaData);
+ self->rowsAffected = fbcmdRowCount(self->cmdMetaData);
+ self->txVersion = fbcmdTransactionVersion(self->cmdMetaData);
+ self->isFetchInProgress = NO;
+
+ if ((self->fetchHandle = fbcmdFetchHandle(self->cmdMetaData)))
+ self->isFetchInProgress = YES;
+
+ if (self->numberOfColumns > 0) {
+ int i;
+
+ self->datatypeCodes = calloc(self->numberOfColumns, sizeof(int));
+ for (i = 0; i < self->numberOfColumns; i++) {
+ const FBCDatatypeMetaData *dmd;
+
+ if ((dmd = fbcmdDatatypeMetaDataAtIndex(self->cmdMetaData, i)))
+ self->datatypeCodes[i] = fbcdmdDatatypeCode(dmd);
+ else
+ self->datatypeCodes[i] = FB_VCharacter;
+ }
+ }
+
+ if (!self->isFetchInProgress) {
+ fbcmdRelease(self->cmdMetaData);
+ self->cmdMetaData = NULL;
+ }
+#if DEBUG
+ else {
+ /* some constraints */
+ if ([_expression hasPrefix:@"INSERT"]) {
+ NSLog(@"an insert shouldn't start a fetch ! ..");
+ }
+ else if ([_expression hasPrefix:@"DELETE"]) {
+ NSLog(@"a delete shouldn't start a fetch ! ..");
+ }
+ else if ([_expression hasPrefix:@"UPDATE"]) {
+ NSLog(@"an update shouldn't start a fetch ! ..");
+ }
+ }
+#endif
+
+ /* setup row handler */
+
+ if (result) {
+ if (delegateRespondsTo.didEvaluateExpression)
+ [delegate adaptorChannel:self didEvaluateExpression:_expression];
+ }
+ else {
+ [self cancelFetch];
+ }
+
+ if (self->sqlLogFile) {
+ FILE *fh;
+ if ((fh = fopen([self->sqlLogFile cString], "a"))) {
+#if DEBUG
+ fprintf(fh, "# %s %3.3g\n", result ? "yes" : "no",
+ -[startDate timeIntervalSinceNow]);
+#else
+ fprintf(fh, "# %s\n", result ? "yes" : "no");
+#endif
+ fflush(fh);
+ fclose(fh);
+ }
+ }
+
+ return result;
+}
+
+/* description */
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@[0x%08X]: open=%s fetching=%s>",
+ NSStringFromClass([self class]),
+ self,
+ [self isOpen] ? "yes" : "no",
+ [self isFetchInProgress] ? "yes" : "no"];
+}
+
+@end /* FrontBaseChannel */
+
+@implementation FrontBaseChannel(PrimaryKeyGeneration)
+
+- (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity {
+ NSArray *pkeys;
+ FrontBase2Adaptor *adaptor;
+ NSString *newKeyExpr;
+ NSDictionary *pkey;
+
+ pkeys = [_entity primaryKeyAttributeNames];
+ adaptor = (id)[[self adaptorContext] adaptor];
+ newKeyExpr = [adaptor newKeyExpression];
+
+ if (newKeyExpr == nil) {
+ NSLog(@"ERROR: missing newkey expression, can't gen pkey for %@",
+ [_entity name]);
+ return nil;
+ }
+
+ if ([pkeys count] != 1) {
+ NSLog(@"no pkeys configured for entity %@", [_entity name]);
+ return nil;
+ }
+
+ *(&pkey) = nil;
+
+ NS_DURING {
+ if ([self evaluateExpression:newKeyExpr]) {
+ NSDictionary *row;
+ NSArray *attrs;
+ id key;
+
+ attrs = [self describeResults];
+ row = [self fetchAttributes:attrs withZone:NULL];
+ [self cancelFetch];
+
+ if ((key = [[row objectEnumerator] nextObject])) {
+ pkey = [NSDictionary dictionaryWithObject:
+ [NSNumber numberWithInt:[key intValue]]
+ forKey:[pkeys objectAtIndex:0]];
+ }
+ }
+ else {
+ NSLog(@"could not evaluate newkey expression: %@", newKeyExpr);
+ }
+ }
+ NS_HANDLER {
+ fprintf(stderr, "newkey failed: %s\n",
+ [[localException description] cString]);
+ fflush(stderr);
+ pkey = nil;
+ }
+ NS_ENDHANDLER;
+
+ return pkey;
+}
+
+@end /* FrontBaseChannel(PrimaryKeyGeneration) */
+
+@implementation FrontBaseChannel(BlobHandling)
+
+- (NSDictionary *)_extractBlobsFromRow:(NSMutableDictionary *)_mrow
+ entity:(EOEntity *)_entity
+{
+ /*
+ Search for BLOB attributes.
+ If a BLOB attribute is found, remove it from mrow and add it's data to
+ blobRow.
+ */
+ FrontBase2Adaptor *adaptor;
+ NSMutableDictionary *blobRow;
+ NSEnumerator *keys;
+ NSString *key;
+
+ adaptor = (FrontBase2Adaptor *)[[self adaptorContext] adaptor];
+#if DEBUG
+ NSAssert(adaptor, @"missing adaptor ..");
+#endif
+
+ /* must use allKeys since we are going to modify mrow */
+ keys = [[_mrow allKeys] objectEnumerator];
+ blobRow = nil;
+
+ while ((key = [keys nextObject])) {
+ EOAttribute *attribute;
+ int fbType;
+
+ attribute = [_entity attributeNamed:key];
+ fbType = [adaptor typeCodeForExternalName:[attribute externalType]];
+
+ if ((fbType == FB_BLOB) || (fbType == FB_CLOB)) {
+ NSData *data;
+ id value;
+
+ value = [_mrow objectForKey:key];
+ data = [value dataValueForFrontBaseType:fbType
+ attribute:attribute];
+ if (data == nil) // EONull
+ continue;
+
+ if (blobRow == nil)
+ blobRow = [NSMutableDictionary dictionaryWithCapacity:4];
+
+ [blobRow setObject:data forKey:key];
+ [_mrow removeObjectForKey:key];
+ }
+ else if (fbType == FB_VCharacter) {
+ /* check for large VARCHARs and handle them like BLOBs.. */
+ id value;
+
+ value = [_mrow objectForKey:key];
+
+ if ([value isKindOfClass:[NSString class]]) {
+ if ([value length] > 2000) {
+ NSData *data;
+
+ data = [value dataValueForFrontBaseType:fbType
+ attribute:attribute];
+ if (data == nil)
+ continue;
+
+ if (blobRow == nil)
+ blobRow = [NSMutableDictionary dictionaryWithCapacity:4];
+
+ [blobRow setObject:data forKey:key];
+ [_mrow removeObjectForKey:key];
+ }
+ }
+ else if ([value isKindOfClass:[NSData class]]) {
+ if ([value length] > 60) {
+ NSData *data;
+
+ data = [value dataValueForFrontBaseType:fbType
+ attribute:attribute];
+ if (data == nil)
+ continue;
+
+ if (blobRow == nil)
+ blobRow = [NSMutableDictionary dictionaryWithCapacity:4];
+
+ [blobRow setObject:data forKey:key];
+ [_mrow removeObjectForKey:key];
+ }
+ }
+ }
+#if 0
+ else {
+ NSLog(@"%@ is *not* a BLOB attribute (type=%i) ..", attribute, fbType);
+ }
+#endif
+ }
+ return blobRow;
+}
+
+- (BOOL)_writeBlobs:(NSDictionary *)_blobs ofRow:(NSMutableDictionary *)_mrow {
+ /*
+ This method writes the blobs and set's the appropriate handle-keys in
+ the row.
+ */
+ if (_blobs) {
+ NSEnumerator *keyEnum;
+ NSString *key;
+
+ keyEnum = [_blobs keyEnumerator];
+ while ((key = [keyEnum nextObject])) {
+ NSData *value;
+ FBCBlobHandle *blob;
+
+ value = [_blobs objectForKey:key];
+
+#if BLOB_DEBUG
+ NSLog(@"writing blob %@ of size %i ...", key, [value length]);
+#endif
+
+ if ((blob = fbcdcWriteBLOB(self->fbdc,
+ (char*)[value bytes],
+ [value length]))) {
+ char blobid[FBBlobHandleByteSize + 4];
+ NSString *blobKey;
+ FBBlobHandle *handle;
+
+ fbcbhGetHandle(blob, blobid);
+
+ blobKey = [NSString stringWithCString:blobid
+ length:FBBlobHandleByteSize + 3];
+#if BLOB_DEBUG
+ NSLog(@" got id %@ for blob %@ ...", blobKey, key);
+#endif
+ if (blobKey == nil) {
+ if (blob)
+ fbcbhRelease(blob);
+ return NO;
+ }
+
+ fbcbhRelease(blob); blob = NULL;
+
+ handle = [[FBBlobHandle alloc] initWithBlobID:blobKey];
+ [_mrow setObject:handle forKey:key];
+ RELEASE(handle); handle = nil;
+ }
+ else {
+ NSLog(@"%@: writing of BLOB %@ failed !", self, key);
+ return NO;
+ }
+ }
+ return YES;
+ }
+ else
+ return YES;
+}
+
+- (BOOL)insertRow:(NSDictionary *)row forEntity:(EOEntity *)entity {
+ EOSQLExpression *sqlexpr = nil;
+ NSMutableDictionary *mrow = nil;
+ NSDictionary *blobRow = nil;
+
+ mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]);
+
+ if (!isOpen)
+ [[ChannelIsNotOpenedException new] raise];
+
+ if((row == nil) || (entity == nil)) {
+ [[[InvalidArgumentException alloc]
+ initWithFormat:@"row and entity arguments for insertRow:forEntity:"
+ @"must not be the nil object"] raise];
+ }
+
+ if([self isFetchInProgress])
+ [[AdaptorIsFetchingException exceptionWithAdaptor:self] raise];
+
+ if(![adaptorContext transactionNestingLevel])
+ [[NoTransactionInProgressException exceptionWithAdaptor:self] raise];
+
+ if(delegateRespondsTo.willInsertRow) {
+ EODelegateResponse response;
+
+ response = [delegate adaptorChannel:self
+ willInsertRow:mrow
+ forEntity:entity];
+ if(response == EODelegateRejects)
+ return NO;
+ else if(response == EODelegateOverrides)
+ return YES;
+ }
+
+ /* extract BLOB attributes */
+
+ blobRow = [self _extractBlobsFromRow:mrow entity:entity];
+
+ /* upload BLOBs */
+
+ if (![self _writeBlobs:blobRow ofRow:mrow])
+ return NO;
+
+ /* insert non-BLOB attributes */
+
+ sqlexpr = [[[adaptorContext adaptor]
+ expressionClass]
+ insertExpressionForRow:mrow
+ entity:entity
+ channel:self];
+
+ if(![self evaluateExpression:[sqlexpr expressionValueForContext:nil]])
+ return NO;
+
+ if(delegateRespondsTo.didInsertRow)
+ [delegate adaptorChannel:self didInsertRow:mrow forEntity:entity];
+
+ return YES;
+}
+
+- (BOOL)updateRow:(NSDictionary *)row
+ describedByQualifier:(EOSQLQualifier *)qualifier
+{
+ /*
+ FrontBaseChannel's -updateRow:describedByQualifier: differs from the
+ EOAdaptorChannel one in that it updates BLOB columns seperatly.
+ */
+ FrontBase2Adaptor *adaptor = (FrontBase2Adaptor *)[adaptorContext adaptor];
+ EOEntity *entity = [qualifier entity];
+ EOSQLExpression *sqlexpr = nil;
+ NSMutableDictionary *mrow = nil;
+ NSDictionary *blobRow = nil;
+
+ self->rowsAffected = 0;
+
+ mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]);
+
+ if (!isOpen)
+ [[ChannelIsNotOpenedException new] raise];
+
+ if(row == nil) {
+ [[[InvalidArgumentException alloc]
+ initWithFormat:@"row argument for updateRow:describedByQualifier: "
+ @"must not be the nil object"] raise];
+ }
+
+ if([self isFetchInProgress])
+ [[AdaptorIsFetchingException exceptionWithAdaptor:self] raise];
+
+ if(![adaptorContext transactionNestingLevel])
+ [[NoTransactionInProgressException exceptionWithAdaptor:self] raise];
+
+ if(delegateRespondsTo.willUpdateRow) {
+ EODelegateResponse response;
+
+ response = [delegate adaptorChannel:self
+ willUpdateRow:mrow
+ describedByQualifier:qualifier];
+ if(response == EODelegateRejects)
+ return NO;
+ else if(response == EODelegateOverrides)
+ return YES;
+ }
+
+ /* extract BLOB attributes */
+
+ blobRow = [self _extractBlobsFromRow:mrow entity:entity];
+
+ /* upload BLOBs */
+
+ if (![self _writeBlobs:blobRow ofRow:mrow])
+ return NO;
+
+ /* update non-BLOB attributes */
+
+ if ([mrow count] > 0) {
+ sqlexpr = [[adaptor expressionClass]
+ updateExpressionForRow:mrow
+ qualifier:qualifier
+ channel:self];
+
+ if(![self evaluateExpression:[sqlexpr expressionValueForContext:nil]])
+ return NO;
+
+ if (self->rowsAffected != 1) {
+ NSLog(@"%s: rows affected: %i", __PRETTY_FUNCTION__, self->rowsAffected);
+ return NO;
+ }
+ }
+
+ /* inform delegate about sucess */
+
+ if(delegateRespondsTo.didUpdateRow) {
+ [delegate adaptorChannel:self
+ didUpdateRow:mrow
+ describedByQualifier:qualifier];
+ }
+ return YES;
+}
+
+- (BOOL)selectAttributes:(NSArray *)attributes
+ describedByQualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ lock:(BOOL)lockFlag
+{
+ static Class EOSortOrderingClass = Nil;
+ NSMutableArray *mattrs;
+ NSEnumerator *fetchOrders;
+ id fo;
+
+ /* automatically add attributes used in fetchOrderings (required by FB) */
+
+ if (EOSortOrderingClass == Nil)
+ EOSortOrderingClass = [EOSortOrdering class];
+
+ mattrs = nil;
+ fetchOrders = [fetchOrder objectEnumerator];
+ while ((fo = [fetchOrders nextObject])) {
+ EOAttribute *attr;
+
+ attr = nil;
+ if ([fo isKindOfClass:EOSortOrderingClass]) {
+ NSString *attrName;
+
+ attrName = [fo key];
+ attr = [[qualifier entity] attributeNamed:attrName];
+ }
+ else {
+ /* EOAttributeOrdering */
+ attr = [fo attribute];
+ }
+
+ if (attr == nil) {
+ NSLog(@"ERROR(%s): could not resolve attribute of sort ordering %@ !",
+ __PRETTY_FUNCTION__, fo);
+ continue;
+ }
+
+ if (mattrs) {
+ if (![mattrs containsObject:attr])
+ [mattrs addObject:attr];
+ }
+ else if (![attributes containsObject:attr]) {
+ mattrs = [[NSMutableArray alloc] initWithArray:attributes];
+ [mattrs addObject:attr];
+ }
+ }
+
+ if (mattrs) {
+ attributes = [mattrs copy];
+ RELEASE(mattrs);
+ AUTORELEASE(attributes);
+ }
+
+ /* continue usual select .. */
+
+ ASSIGN(self->selectedAttributes, attributes);
+
+ return [super selectAttributes:attributes
+ describedByQualifier:qualifier
+ fetchOrder:fetchOrder
+ lock:lockFlag];
+}
+
+@end /* FrontBaseChannel(BlobHandling) */
+
+void __link_FBChannel() {
+ // used to force linking of object file
+ __link_FBChannel();
+}
--- /dev/null
+/*
+ FBContext.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBContext.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_Context_H___
+#define ___FB_Context_H___
+
+#import <GDLAccess/EOAdaptorContext.h>
+#import "FBHeaders.h"
+
+@interface FBContext : EOAdaptorContext
+
++ (FBContext *)activeContext; // used by sybase callback procedures
+
+- (BOOL)primaryBeginTransaction;
+- (BOOL)primaryCommitTransaction;
+- (BOOL)primaryRollbackTransaction;
+
+@end
+
+@interface FrontBaseContext : FBContext
+@end
+
+#endif
--- /dev/null
+/*
+ FBContext.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBContext.m 1 2004-08-20 10:38:46Z znek $
+
+#import "FBContext.h"
+#import "FBChannel.h"
+#import "common.h"
+
+@implementation FBContext
+
+static FBContext *context = nil;
+
++ (FBContext *)activeContext {
+ return context;
+}
+
+- (void)channelDidInit:_channel {
+ if ([channels count] > 0) {
+ [NSException raise:@"TooManyOpenChannelsException"
+ format:@"SybaseAdaptor10 only supports one channel per context"];
+ }
+ [super channelDidInit:_channel];
+}
+
+- (BOOL)primaryBeginTransaction {
+ return YES;
+}
+
+- (BOOL)primaryCommitTransaction {
+ FrontBaseChannel *channel;
+ BOOL result;
+
+ context = self;
+ channel = [[channels lastObject] nonretainedObjectValue];
+ //NSLog(@"committing channel %@", channel);
+ result = [channel evaluateExpression:@"COMMIT"];
+ context = nil;
+ return result;
+}
+
+- (BOOL)primaryRollbackTransaction {
+ FrontBaseChannel *channel;
+ BOOL result;
+
+ context = self;
+ channel = [[channels lastObject] nonretainedObjectValue];
+ //NSLog(@"rolling back channel %@", channel);
+ result = [channel evaluateExpression:@"ROLLBACK"];
+ context = nil;
+ return result;
+}
+
+- (BOOL)canNestTransactions {
+ return YES;
+}
+
+// NSCopying methods
+
+- (id)copyWithZone:(NSZone *)zone {
+ // copy is needed during creation of NSNotification object
+ return RETAIN(self);
+}
+
+@end
+
+@implementation FrontBaseContext
+@end
+
+void __link_FBContext() {
+ // used to force linking of object file
+ __link_FBContext();
+}
--- /dev/null
+/*
+ FBException.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBException.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_Exception_H___
+#define ___FB_Exception_H___
+
+#import <Foundation/NSException.h>
+#import "FBHeaders.h"
+
+@interface FrontBaseException : NSException
+@end
+
+@interface FBCouldNotOpenChannelException : FrontBaseException
+@end
+
+#endif
--- /dev/null
+/*
+ FBException.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBException.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/Foundation.h>
+#import <GDLAccess/EOAccess.h>
+#import "FBException.h"
+
+@implementation FrontBaseException
+@end /* FrontBaseException */
+
+@implementation FBCouldNotOpenChannelException
+@end /* FBCouldNotOpenChannelException */
--- /dev/null
+/*
+ FBHeaders.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBHeaders.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_Headers_H___
+#define ___FB_Headers_H___
+
+#include <FBCAccess/FBCAccess.h>
+
+typedef struct {
+ unsigned char blobType;
+ unsigned int blobSize;
+ unsigned char *blobData;
+} FBInlineBlob;
+
+typedef struct {
+ unsigned char blobType;
+ unsigned char *blobHandle;
+} FBHandleBlob;
+
+#endif
--- /dev/null
+/*
+ FBSQLExpression.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBSQLExpression.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_SQLExpression_H___
+#define ___FB_SQLExpression_H___
+
+#include <GDLAccess/EOSQLExpression.h>
+
+@class NSString, NSArray;
+@class EOSQLQualifier, EOAdaptorChannel;
+
+@interface FBSQLExpression : EOSQLExpression
+
++ (Class)selectExpressionClass;
+
+@end
+
+@interface FBSelectSQLExpression : EOSelectSQLExpression
+{
+ BOOL lock;
+}
+
+- (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel;
+
+@end
+
+#endif
--- /dev/null
+/*
+ FBSQLExpression.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBSQLExpression.m 1 2004-08-20 10:38:46Z znek $
+
+#include <Foundation/Foundation.h>
+#include <GDLAccess/EOAccess.h>
+#include "FBSQLExpression.h"
+
+@implementation FBSQLExpression
+
++ (int)version {
+ return [super version] + 0 /* v1 */;
+}
++ (void)initialize {
+ NSAssert([super version] == 1, @"invalid superclass version !");
+}
+
++ (Class)selectExpressionClass {
+ return [FBSelectSQLExpression class];
+}
+
+@end
+
+@implementation FBSelectSQLExpression
+
+- (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel
+{
+ self->lock = flag;
+
+ return [super selectExpressionForAttributes:attributes
+ lock:flag
+ qualifier:qualifier
+ fetchOrder:fetchOrder
+ channel:channel];
+}
+
+- (NSString *)lockClause {
+#warning no holdlock !!!
+ return @"";
+#if 0
+ return (self->lock)
+ ? @" HOLDLOCK"
+ : @"";
+#endif
+}
+
+@end
+
+void __link_FBSQLExpression() {
+ // used to force linking of object file
+ __link_FBSQLExpression();
+}
--- /dev/null
+/*
+ FBValues.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FrontBase Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBValues.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_Values_H___
+#define ___FB_Values_H___
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSDate.h>
+#import <Foundation/NSValue.h>
+#import <GDLAccess/EONull.h>
+#import "FBException.h"
+#import "FBHeaders.h"
+
+@class EOAttribute;
+@class FrontBaseChannel;
+
+@protocol FBValues
+
++ (id)valueFromBytes:(const char *)_bytes
+ length:(unsigned)_length
+ frontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel;
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute;
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute;
+
+@end
+
+@interface NSString(FBValues) < FBValues >
+@end
+
+@interface NSNumber(FBValues) < FBValues >
+@end
+
+@interface NSData(FBValues) < FBValues >
+@end
+
+@interface NSCalendarDate(FBValues) < FBValues >
+@end
+
+@interface EONull(FBValues)
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute;
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute;
+
+@end
+
+#endif
--- /dev/null
+/*
+ FBValues.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FBValues.m 1 2004-08-20 10:38:46Z znek $
+
+#include <string.h>
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#include <stdlib.h>
+#import "common.h"
+#include "FBException.h"
+#import <Foundation/NSDate.h>
+
+static Class NumberClass = Nil;
+
+@interface FBDataTypeMappingException : FrontBaseException
+@end
+
+@interface NSTimeZone(UsedPrivates)
+- (NSTimeZoneDetail *)timeZoneDetailForDate:(NSDate *)_date;
+@end
+
+@implementation FBDataTypeMappingException
+
+- (id)initWithObject:(id)_obj forAttribute:(EOAttribute *)_attr
+ andFrontBaseType:(int)_fb inChannel:(FrontBaseChannel *)_channel
+{
+ NSString *typeName = nil;
+
+ typeName =
+ [(id)[[_channel adaptorContext] adaptor] externalNameForTypeCode:_fb];
+
+ if (typeName == nil)
+ typeName = [NSString stringWithFormat:@"Type[%i]", _fb];
+
+ [self setName:@"FBDataTypeMappingNotSupported"];
+ [self setReason:[NSString stringWithFormat:
+ @"mapping between %@<Class:%@> and "
+ @"frontbase type %@ is not supported",
+ [_obj description],
+ NSStringFromClass([_obj class]),
+ typeName]];
+
+ [self setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ _attr, @"attribute",
+ _channel, @"channel",
+ _obj, @"object",
+ nil]];
+ return self;
+}
+
+@end /* FBDataTypeMappingException */
+
+static inline void FmtRaiseMapExc(id _object,
+ int _fb,
+ EOAttribute *_attribute,
+ id _channel) {
+ NSLog(@"%s: FmtRaiseMapExc objectClass=%@ object=%@ "
+ @"type=%i typeName=%@ attribute=%@",
+ __PRETTY_FUNCTION__,
+ NSStringFromClass([_object class]),
+ _object,
+ _fb,
+ [(id)[[_channel adaptorContext] adaptor] externalNameForTypeCode:_fb],
+ _attribute);
+
+ [[[FBDataTypeMappingException alloc]
+ initWithObject:_object
+ forAttribute:_attribute
+ andFrontBaseType:_fb
+ inChannel:_channel] raise];
+}
+static inline void RaiseMapExc(id _object, int _type,
+ EOAttribute *_attribute,
+ id _channel) {
+ NSLog(@"%s: RaiseMapExc objectClass=%@ object=%@ type=%i name=%@ attribute=%@",
+ __PRETTY_FUNCTION__,
+ NSStringFromClass([_object class]),
+ _object,
+ _type,
+ [(id)[[_channel adaptorContext] adaptor] externalNameForTypeCode:_type],
+ _attribute);
+
+ [[[FBDataTypeMappingException alloc]
+ initWithObject:_object
+ forAttribute:_attribute
+ andFrontBaseType:_type
+ inChannel:_channel] raise];
+}
+
+@implementation NSString(FBValues)
+
++ (id)valueFromBytes:(const char *)_bytes length:(unsigned)_length
+ frontBaseType:(int)_fb attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel
+{
+ id result = nil;
+
+ switch (_fb) {
+ case FB_Character:
+ case FB_VCharacter:
+ result = [self stringWithCString:_bytes length:_length];
+ break;
+
+ case FB_BLOB:
+ case FB_CLOB:
+ result = [self stringWithCString:_bytes length:_length];
+ break;
+
+ case FB_SmallInteger:
+ result = [NSString stringWithFormat:@"%i", *(short *)_bytes];
+ break;
+ case FB_Integer:
+ result = [NSString stringWithFormat:@"%i", *(int *)_bytes];
+ break;
+
+ case FB_Real:
+ case FB_Double:
+ result = [NSString stringWithFormat:@"%g", *(double *)_bytes];
+ break;
+
+ case FB_Float:
+ result = [NSString stringWithFormat:@"%g", *(float *)_bytes];
+ break;
+
+ default:
+ FmtRaiseMapExc(self, _fb, _attribute, _channel);
+ }
+
+ return result;
+}
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ /* NSString */
+ return [NSData dataWithBytes:[self cString] length:[self cStringLength]];
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ /* NSString */
+ switch (_type) {
+ case FB_BLOB:
+ return [[NSData dataWithBytes:[self cString] length:[self cStringLength]]
+ stringValueForFrontBaseType:_type attribute:_attribute];
+
+ case FB_Character:
+ case FB_VCharacter:
+ case FB_CLOB: {
+ id expr = nil;
+
+ expr = [[[EOQuotedExpression alloc] initWithExpression:self
+ quote:@"'" escape:@"''"]
+ autorelease];
+ expr = [expr expressionValueForContext:nil];
+ return expr;
+ }
+
+ case FB_Bit:
+ case FB_SmallInteger:
+ case FB_Integer:
+ case FB_Real:
+ case FB_Double:
+ case FB_Numeric:
+ case FB_Decimal:
+ /* NSLog(@"returning %@ for number type", self); */
+ return self;
+ }
+
+ RaiseMapExc(self, _type, _attribute, nil);
+
+ NSLog(@"impossible condition reached: %@", self);
+ abort();
+ return nil;
+}
+
+@end /* NSString(FBValues) */
+
+@implementation NSNumber(FBValues)
+
+#define ReturnNumber(sybtype, def) {\
+ if (valueType == -1) \
+ return [NumberClass def *(sybtype*)_bytes]; \
+ else if (valueType == 'c') \
+ return [NumberClass numberWithChar:*(sybtype*)_bytes]; \
+ else if (valueType == 'C') \
+ return [NumberClass numberWithUnsignedChar:*(sybtype*)_bytes]; \
+ else if (valueType == 's') \
+ return [NumberClass numberWithShort:*(sybtype*)_bytes]; \
+ else if (valueType == 'S') \
+ return [NumberClass numberWithUnsignedShort:*(sybtype*)_bytes]; \
+ else if (valueType == 'i') \
+ return [NumberClass numberWithInt:*(sybtype*)_bytes]; \
+ else if (valueType == 'I') \
+ return [NumberClass numberWithUnsignedInt:*(sybtype*)_bytes]; \
+ else if (valueType == 'f') \
+ return [NumberClass numberWithFloat:*(sybtype*)_bytes]; \
+ else if (valueType == 'd') \
+ return [NumberClass numberWithDouble:*(sybtype*)_bytes]; \
+ else \
+ [NSException raise:@"InvalidValueTypeException" \
+ format:@"value type %c is not recognized", valueType];\
+ return nil; \
+ }
+
++ (id)valueFromBytes:(const char *)_bytes length:(unsigned)_length
+ frontBaseType:(int)_fb attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel
+{
+ char valueType;
+
+ if ([_attribute valueType])
+ valueType = [[_attribute valueType] cString][0];
+ else
+ valueType = -1;
+
+ switch (_fb) {
+ case FB_Character:
+ case FB_VCharacter: {
+ switch (valueType) {
+ case 'c': return [NumberClass numberWithChar:atoi(_bytes)];
+ case 'C': return [NumberClass numberWithUnsignedChar:atol(_bytes)];
+ case 's': return [NumberClass numberWithShort:atoi(_bytes)];
+ case 'S': return [NumberClass numberWithUnsignedShort:atol(_bytes)];
+ case 'i': return [NumberClass numberWithInt:atoi(_bytes)];
+ case 'I': return [NumberClass numberWithUnsignedInt:atol(_bytes)];
+ case 'f': return [NumberClass numberWithFloat:atof(_bytes)];
+ case 'd': return [NumberClass numberWithDouble:atof(_bytes)];
+ default:
+ [NSException raise:@"InvalidValueTypeException"
+ format:@"value type %c is not recognized",
+ valueType];
+ return nil;
+ }
+ }
+
+ case FB_Boolean: {
+ unsigned char v;
+ v = *(unsigned char *)_bytes;
+ return [NumberClass numberWithBool:v];
+ }
+
+ case FB_Integer: {
+ int v;
+ v = *(int *)_bytes;
+ return [NumberClass numberWithInt:v];
+ }
+ case FB_SmallInteger: {
+ short v;
+ v = *(short *)_bytes;
+ return [NumberClass numberWithShort:v];
+ }
+
+ case FB_Real:
+ case FB_Double:
+ ReturnNumber(double, numberWithDouble:);
+
+ case FB_Float:
+ ReturnNumber(float, numberWithFloat:);
+
+ case FB_Numeric:
+ case FB_Decimal:
+#if 0
+ if (_fmt->scale > 0) {
+ ReturnNumber(CS_REAL, numberWithDouble:);
+ }
+ else {
+ ReturnNumber(int, numberWithInt:);
+ }
+#endif
+ ReturnNumber(double, numberWithDouble:);
+
+ default:
+ FmtRaiseMapExc(self, _fb, _attribute, _channel);
+ }
+
+ [NSException raise:@"InvalidFrontBaseValueStateException"
+ format:@"reached invalid state in sybase NSNumber handler"];
+
+ return nil;
+}
+
+#undef ReturnNumber
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ RaiseMapExc(self, _type, _attribute, nil);
+ return nil;
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ /* NSNumber */
+ switch (_type) {
+ case FB_Boolean:
+ case FB_Bit:
+ case FB_SmallInteger:
+ case FB_Integer:
+ case FB_Real:
+ case FB_Float:
+ case FB_Numeric:
+ case FB_Decimal:
+ return [self stringValue];
+
+ case FB_Character:
+ case FB_VCharacter:
+ return [NSString stringWithFormat:@"'%s'", [[self stringValue] cString]];
+
+ default:
+ RaiseMapExc(self, _type, _attribute, nil);
+ }
+ return nil;
+}
+
+@end /* NSNumber(FBValues) */
+
+@implementation NSData(FBValues)
+
++ (id)valueFromBytes:(const char *)_bytes length:(unsigned)_length
+ frontBaseType:(int)_fb attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel
+{
+ switch (_fb) {
+ case FB_Bit:
+ case FB_SmallInteger:
+ case FB_Integer:
+ case FB_Real:
+ case FB_Float:
+ case FB_Numeric:
+ case FB_Decimal:
+ case FB_Character:
+ case FB_VCharacter:
+ case FB_BLOB:
+ case FB_CLOB:
+ return [[[self alloc] initWithBytes:_bytes length:_length] autorelease];
+
+ default:
+ FmtRaiseMapExc(self, _fb, _attribute, _channel);
+ }
+ return nil;
+}
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ return self;
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attribute
+{
+ switch (_type) {
+ case FB_Boolean:
+ return [[NumberClass numberWithChar:*(char *)[self bytes]] stringValue];
+
+ case FB_SmallInteger:
+ return [[NumberClass numberWithShort:*(short *)[self bytes]] stringValue];
+
+ case FB_Integer:
+ return [[NumberClass numberWithInt:*(int *)[self bytes]] stringValue];
+
+ case FB_Real:
+ case FB_Double:
+ return [[NumberClass numberWithDouble:*(double *)[self bytes]]
+ stringValue];
+
+ case FB_Float:
+ return [[NumberClass numberWithFloat:*(float *)[self bytes]] stringValue];
+
+ case FB_Character:
+ case FB_VCharacter:
+ case FB_CLOB:
+ case FB_BLOB: {
+ unsigned final_length = [self length];
+ char *cstr = NULL, *tmp = NULL;
+ unsigned cnt;
+ const char *iBytes = [self bytes];
+
+ if (final_length == 0) return @"NULL";
+
+ final_length = 2 + 2 * final_length + 1;
+ cstr = objc_atomic_malloc(final_length + 4);
+ tmp = cstr + 2;
+
+ cstr[0] = '\0';
+ strcat(cstr, "0x");
+
+ for (cnt = 0; cnt < [self length]; cnt++, tmp += 2)
+ sprintf(tmp, "%02X", (unsigned char)iBytes[cnt]);
+ *tmp = '\0';
+
+ return [[[NSString alloc] initWithCStringNoCopy:cstr length:cstr?strlen(cstr):0 freeWhenDone:YES] autorelease];
+ }
+
+ default:
+ RaiseMapExc(self, _type, _attribute, nil);
+ }
+ return nil;
+}
+
+@end /* NSData(FBValues) */
+
+// 1234567890123456789012345
+// Frontbase Date: 1997-10-21 21:52:26+08:00
+static NSString *FRONTBASE_DATE_FORMAT = @"%Y-%m-%d %H:%M:%S%z";
+
+@implementation NSDate(FBValues)
+
++ (id)valueFromBytes:(const char *)_bytes length:(unsigned)_length
+ frontBaseType:(int)_fb attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel
+{
+ /* NSDate */
+ return [NSCalendarDate valueFromBytes:_bytes length:_length
+ frontBaseType:_fb attribute:_attribute
+ adaptorChannel:_channel];
+}
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attr
+{
+ /* NSDate */
+ NSCalendarDate *cdate;
+
+ cdate = [NSCalendarDate dateWithTimeIntervalSince1970:
+ [self timeIntervalSince1970]];
+
+ return [cdate dataValueForFrontBaseType:_type attribute:_attr];
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attr
+{
+ /* NSDate */
+ NSCalendarDate *cdate;
+
+ cdate = [NSCalendarDate dateWithTimeIntervalSince1970:
+ [self timeIntervalSince1970]];
+
+ return [cdate stringValueForFrontBaseType:_type attribute:_attr];
+}
+
+@end
+
+@implementation NSCalendarDate(FBValues)
+
++ (id)valueFromBytes:(const char *)_bytes length:(unsigned)_length
+ frontBaseType:(int)_fb attribute:(EOAttribute *)_attribute
+ adaptorChannel:(FrontBaseChannel *)_channel
+{
+ /* NSCalendarDate */
+ switch (_fb) {
+ case FB_TimestampTZ: {
+ /* a string of length 25 */
+ NSCalendarDate *date;
+ NSString *str, *stampstr, *tzstr;
+
+#if DEBUG
+ NSAssert2(_length >= 25,
+ @"byte values for date creation are too short "
+ @"(len required is 25, got %i), attribute=%@",
+ _length, _attribute);
+
+ if (_length != 25) {
+ NSLog(@"WARNING: invalid length, should be '25', got %i, attribute %@",
+ _length, _attribute);
+ }
+#endif
+
+ stampstr = [NSString stringWithCString:_bytes length:19];
+ tzstr = [NSString stringWithCString:(_bytes + 19) length:3];
+ str = [NSString stringWithCString:(_bytes + 23) length:2];
+ tzstr = [tzstr stringByAppendingString:str];
+ str = [stampstr stringByAppendingString:tzstr];
+
+ date = [NSCalendarDate dateWithString:str
+ calendarFormat:FRONTBASE_DATE_FORMAT];
+#if DEBUG
+ if (date == nil) {
+ NSLog(@"ERROR: couldn't construct calendar date from "
+ @"string %@ (src=%@) column %@.%@ "
+ @"(%i bytes), format=%@",
+ str, [NSString stringWithCString:_bytes length:19],
+ [[_attribute entity] externalName],
+ [_attribute columnName],
+ _length, date);
+ }
+#if 0
+ else {
+ NSLog(@"info: could construct calendar date from string %@ (len=%i)",
+ str, _length);
+ }
+#endif
+#endif
+ return date;
+ }
+
+ case FB_Character:
+ case FB_VCharacter:
+ case FB_Date:
+ case FB_Timestamp: {
+ NSTimeZone *serverTimeZone;
+ NSCalendarDate *date;
+ NSString *formattedDate;
+ NSString *format;
+
+ formattedDate = [NSString stringWithCString:_bytes length:_length];
+
+ serverTimeZone = [_attribute serverTimeZone];
+ format = [_attribute calendarFormat];
+
+ if (serverTimeZone == nil)
+ serverTimeZone = [NSTimeZone localTimeZone];
+ if (format == nil)
+ format = FRONTBASE_DATE_FORMAT;
+
+ date = [NSCalendarDate dateWithString:formattedDate
+ calendarFormat:format];
+ if (date == nil) {
+ NSLog(@"ERROR(%s): could not construct date from "
+ @"value '%@' with format '%@'",
+ __PRETTY_FUNCTION__, formattedDate, format);
+ }
+ return date;
+ }
+
+ default:
+ FmtRaiseMapExc(self, _fb, _attribute, _channel);
+ }
+ return nil;
+}
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attr
+{
+ /* NSCalendarDate */
+ RaiseMapExc(self, _type, _attr, nil);
+ return nil;
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attr
+{
+ /* NSCalendarDate */
+
+ self = [self copy]; /* copy to rescue timezone setting */
+ [self autorelease];
+
+ switch (_type) {
+ case FB_TimestampTZ: {
+ NSTimeZone *serverTimeZone;
+ NSString *str;
+ NSTimeInterval timeZoneOffset;
+ int i, j;
+
+ serverTimeZone = [_attr serverTimeZone];
+
+ if (serverTimeZone == nil)
+ serverTimeZone = [NSTimeZone localTimeZone];
+
+#if NeXT_Foundation_LIBRARY
+ timeZoneOffset = [serverTimeZone secondsFromGMTForDate:self];
+#else
+ timeZoneOffset = [[serverTimeZone timeZoneDetailForDate:self]
+ timeZoneSecondsFromGMT];
+#endif
+
+ [self setTimeZone:serverTimeZone];
+
+ i = timeZoneOffset > 0;
+ j = (timeZoneOffset > 0 ? timeZoneOffset : -timeZoneOffset) / 60;
+
+ str = [NSString stringWithFormat:
+ @"TIMESTAMP '%02i-%02i-%02i %02i:%02i:%02i%s%02i:%02i'",
+ [self yearOfCommonEra],
+ [self monthOfYear],
+ [self dayOfMonth],
+ [self hourOfDay],
+ [self minuteOfHour],
+ [self secondOfMinute],
+ i ? "+":"-",
+ j / 60, j % 60];
+ return str;
+ }
+
+ case FB_Date: {
+ NSTimeZone *serverTimeZone;
+ NSString *format;
+ id expr;
+
+ serverTimeZone = [_attr serverTimeZone];
+ format = [_attr calendarFormat];
+ expr = nil;
+
+ if (serverTimeZone == nil)
+ serverTimeZone = [NSTimeZone localTimeZone];
+
+ if (format == nil)
+ format = FRONTBASE_DATE_FORMAT;
+
+ [self setTimeZone:serverTimeZone];
+
+ expr = [self descriptionWithCalendarFormat:format];
+ expr = [[EOQuotedExpression alloc] initWithExpression:expr
+ quote:@"'" escape:@"''"];
+ [expr autorelease];
+ expr = [expr expressionValueForContext:nil];
+ expr = [@"TIMESTAMP " stringByAppendingString:expr];
+
+ return expr;
+ }
+
+ default:
+ RaiseMapExc(self, _type, _attr, nil);
+ }
+ return nil;
+}
+
+@end /* NSCalendarDate(FBValues) */
+
+@implementation EONull(FBValues)
+
+- (NSData *)dataValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attr
+{
+ return nil;
+}
+
+- (NSString *)stringValueForFrontBaseType:(int)_type
+ attribute:(EOAttribute *)_attr
+{
+ return @"null";
+}
+
+@end /* EONull(FBValues) */
+
+void __init_FBValues(void) {
+ NumberClass = [NSNumber class];
+}
+
+void __link_FBValues() {
+ // used to force linking of object file
+ __link_FBValues();
+ __init_FBValues();
+}
--- /dev/null
+/*
+ FBAdaptor.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FrontBase2Adaptor.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_Adaptor_H___
+#define ___FB_Adaptor_H___
+
+/*
+ The FB adaptor.
+
+ The connection dictionary of this adaptor understands these keys:
+ hostName
+ userName
+ password
+ databaseName
+ databasePassword
+ transactionIsolationLevel
+ lockingDiscipline
+*/
+
+#import <Foundation/NSMapTable.h>
+#import <GDLAccess/EOAdaptor.h>
+#import <GDLAccess/EOAttribute.h>
+#import "FBHeaders.h"
+
+@class NSString, NSMutableDictionary;
+@class FrontBaseChannel;
+
+extern NSString *FBNotificationName;
+
+@interface FrontBase2Adaptor : EOAdaptor
+{
+@private
+ NSMapTable *typeNameToCode;
+ NSMapTable *typeCodeToName;
+}
+
+- (id)initWithName:(NSString *)_name;
+
+/* connection management */
+
+- (NSString *)serverName;
+- (NSString *)loginName;
+- (NSString *)loginPassword;
+- (NSString *)databaseName;
+- (NSString *)databasePassword;
+- (NSString *)transactionIsolationLevel;
+- (NSString *)lockingDiscipline;
+
+/* key generation */
+
+- (NSString *)newKeyExpression;
+
+/* value formatting */
+
+- (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute;
+
+/* classes used */
+
+- (Class)adaptorContextClass; // FrontBaseContext
+- (Class)adaptorChannelClass; // FrontBaseChannel
+- (Class)expressionClass; // FBSQLExpression
+
+@end
+
+@interface FrontBase2Adaptor(ExternalTyping)
+
+- (int)typeCodeForExternalName:(NSString *)_typeName;
+- (NSString *)externalNameForTypeCode:(int)_typeCode;
+
+- (BOOL)isInternalBlobType:(int)_type;
+- (BOOL)isBlobAttribute:(EOAttribute *)_attr;
+- (BOOL)isValidQualifierType:(NSString *)_typeName;
+- (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr;
+
+@end
+
+#endif
--- /dev/null
+/*
+ FBAdaptor.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: FrontBase2Adaptor.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+
+NSString *FBNotificationName = @"FBNotification";
+
+@interface FrontBase2Adaptor(FetchUserTypes)
+- (void)_fetchUserTypes;
+@end
+
+@implementation FrontBase2Adaptor
+
++ (void)initialize {
+ static BOOL isInitialized = NO;
+
+ if (!isInitialized) {
+ void __init_FBValues(void);
+ isInitialized = YES;
+ __init_FBValues();
+ }
+}
+
+- (id)initWithName:(NSString *)_name {
+ if ((self = [super initWithName:_name])) {
+ }
+ return self;
+}
+
+#if !LIB_FOUNDATION_BOEHM_GC
+- (void)dealloc {
+ if (self->typeNameToCode) {
+ NSFreeMapTable(self->typeNameToCode);
+ self->typeCodeToName = NULL;
+ }
+ if (self->typeCodeToName) {
+ NSFreeMapTable(self->typeCodeToName);
+ self->typeCodeToName = NULL;
+ }
+ [super dealloc];
+}
+#endif
+
+/* NSCopying methods */
+
+- (id)copyWithZone:(NSZone *)_zone {
+ // copy is needed during creation of NSNotification object
+ return RETAIN(self);
+}
+
+/* connections */
+
+- (NSString *)serverName {
+ NSString *serverName;
+
+ serverName = [[self connectionDictionary] objectForKey:@"hostName"];
+
+ return AUTORELEASE([serverName copy]);
+}
+- (NSString *)loginName {
+ return AUTORELEASE([[[self connectionDictionary]
+ objectForKey:@"userName"] copy]);
+}
+- (NSString *)loginPassword {
+ return AUTORELEASE([[[self connectionDictionary]
+ objectForKey:@"password"] copy]);
+}
+- (NSString *)databaseName {
+ return AUTORELEASE([[[self connectionDictionary]
+ objectForKey:@"databaseName"] copy]);
+}
+- (NSString *)databasePassword {
+ return AUTORELEASE([[[self connectionDictionary]
+ objectForKey:@"databasePassword"] copy]);
+}
+
+- (NSString *)transactionIsolationLevel {
+ return AUTORELEASE([[[self connectionDictionary]
+ objectForKey:@"transactionIsolationLevel"] copy]);
+}
+- (NSString *)lockingDiscipline {
+ return AUTORELEASE([[[self connectionDictionary]
+ objectForKey:@"lockingDiscipline"] copy]);
+}
+
+/* key generation */
+
+- (NSString *)newKeyExpression {
+ return AUTORELEASE([[[self pkeyGeneratorDictionary]
+ objectForKey:@"newKeyExpression"]
+ copy]);
+}
+
+/* formatting values */
+
+- (NSString *)formatAttribute:(EOAttribute *)_attribute {
+ return [NSString stringWithFormat:@"\"%s\"",
+ [[_attribute columnName] cString]];
+}
+
+- (NSString *)lowerExpressionForTextAttributeNamed:(NSString *)_attrName {
+ return [NSString stringWithFormat:@"LOWER(%@)", _attrName];
+}
+
+- (NSString *)expressionForTextValue:(id)_value {
+ return [_value lowercaseString];
+}
+
+- (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName {
+ return [NSString stringWithFormat:@"CAST(%@ AS VARCHAR(255))", _attrName];
+}
+
+- (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute {
+ int fbType;
+ NSString *result;
+
+ fbType = [self typeCodeForExternalName:[attribute externalType]];
+ result = [value stringValueForFrontBaseType:fbType
+ attribute:attribute];
+
+#if 0
+ NSLog(@"formatting value %@ result %@", value, result);
+ NSLog(@" value class %@ attr %@ attr type %@",
+ [value class], attribute, [attribute externalType]);
+#endif
+ return result;
+}
+
+/* adaptor info */
+
+- (Class)adaptorContextClass {
+ return [FrontBaseContext class];
+}
+- (Class)adaptorChannelClass {
+ return [FrontBaseChannel class];
+}
+
+- (Class)expressionClass {
+ return [FBSQLExpression class];
+}
+
+@end /* FrontBase2Adaptor */
--- /dev/null
+#
+# GNUmakefile
+#
+# Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+#
+# Author: Helge Hess (helge.hess@mdlink.de)
+#
+# This file is part of the FrontBase Adaptor Library
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; see the file COPYING.LIB.
+# If not, write to the Free Software Foundation,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# $Id: GNUmakefile 1 2004-08-20 10:38:46Z znek $
+
+include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/common.make
+
+CAN_COMPILE_FB = \
+ $(shell ./cancompile.sh $(GNUSTEP_TARGET_CPU) $(GNUSTEP_TARGET_OS))
+
+ifeq ($(CAN_COMPILE_FB),yes)
+
+GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_LOCAL_ROOT)
+
+BUNDLE_NAME = FrontBase2
+
+FrontBase2_OBJC_FILES = \
+ FBSQLExpression.m \
+ FBException.m \
+ FrontBase2Adaptor.m \
+ FBAdaptor+Types.m \
+ FBContext.m \
+ FBChannel.m \
+ EOAttribute+FB.m \
+ NSString+FB.m \
+ FBValues.m \
+ FBChannel+Model.m \
+ FBBlobHandle.m \
+
+FrontBase2_PRINCIPAL_CLASS = FrontBase2Adaptor
+FrontBase2_RESOURCE_FILES = Info.plist Version
+
+BUNDLE_INSTALL = FrontBase2
+BUNDLE_INSTALL_DIR = $(GNUSTEP_SYSTEM_ROOT)/Libraries/Adaptors
+
+# Use .gdladaptor as the bundle extension
+BUNDLE_EXTENSION = .gdladaptor
+
+# tool stuff
+
+TOOL_NAME = fbtest
+
+fbtest_OBJC_FILES = fbtest.m
+#fbtest_OBJC_FILES += $(FrontBase2_OBJC_FILES)
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/bundle.make
+#include $(GNUSTEP_MAKEFILES)/tool.make
+-include GNUmakefile.postamble
+
+else # cannot compile FB
+
+cannotcompile :
+ echo "cannot compile FrontBase 2.x adaptor for OS $(GNUSTEP_TARGET_OS) CPU $(GNUSTEP_TARGET_CPU)"
+
+all :: cannotcompile
+
+clean ::
+
+install :: cannotcompile
+
+endif
--- /dev/null
+# $Id: GNUmakefile.preamble 1 2004-08-20 10:38:46Z znek $
+
+FRONTBASE = ./fb2/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)
+
+ADDITIONAL_INCLUDE_DIRS += -I.. -I../GDLAccess
+
+ADDITIONAL_LIB_DIRS += \
+ -L../GDLAccess/$(GNUSTEP_OBJ_DIR) \
+ -L../$(GNUSTEP_OBJ_DIR) \
+
+FrontBase2_BUNDLE_LIBS += \
+ -lEOControl \
+ -lNGExtensions \
+ -lNGStreams \
+ -lGDLAccess \
+
+ifeq ($(FOUNDATION_LIB),nx)
+
+FrontBase2_BUNDLE_LIBS += -lFoundationExt
+FrontBase2_LDFLAGS += -framework FBCAccess -framework Foundation
+
+else
+
+ifeq ($(uselib),yes)
+
+FrontBase2_BUNDLE_LIBS += -lFBCAccess
+
+else
+
+ADDITIONAL_INCLUDE_DIRS += -I$(FRONTBASE)/include
+ADDITIONAL_LIB_DIRS += -L$(FRONTBASE)/lib
+
+ifneq ($(GNUSTEP_TARGET_OS),mingw32)
+FrontBase2_LDFLAGS += $(FRONTBASE)/lib/FBCAccess.o
+FrontBase2_BUNDLE_LIBS += -lGDLAccess
+else
+FrontBase2_LIB_DIRS += -L$(FRONTBASE)/lib
+FrontBase2_BUNDLE_LIBS += \
+ -lFBCAccessImp \
+ -lGDLAccess \
+ -lEOControl -lFoundation -lobjc
+endif
+
+endif # uselib,yes
+endif # FOUNDATION_LIB,nx
+
+#ifeq ($(GNUSTEP_TARGET_OS),mingw32)
+#fbtest_LIB_DIRS += -L$(FRONTBASE)/lib
+#fbtest_TOOL_LIBS += -lFBCAccessImp
+#endif
+
+ADDITIONAL_TOOL_LIBS += \
+ -lEOControl \
+ -lNGExtensions \
+ -lNGStreams \
+ -lGDLAccess \
--- /dev/null
+{
+ NSPrincipalClass = FrontBase2Adaptor;
+ NSExecutable = FrontBase2;
+}
--- /dev/null
+/*
+ NSString+FB.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: NSString+FB.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_NSString_H___
+#define ___FB_NSString_H___
+
+#import <Foundation/NSString.h>
+
+@interface NSString(FBMiscStrings)
+
+- (NSString *)_sybModelMakeInstanceVarName;
+- (NSString *)_sybModelMakeClassName;
+- (NSString *)_sybStringWithCapitalizedFirstChar;
+- (NSString *)_sybStripEndSpaces;
+
+@end
+
+#endif
--- /dev/null
+/*
+ NSString+FB.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: NSString+FB.m 1 2004-08-20 10:38:46Z znek $
+
+#if LIB_FOUNDATION_BOEHM_GC
+# include <objc/gc.h>
+#endif
+
+#import "NSString+FB.h"
+#import "common.h"
+
+@implementation NSString(FBMiscStrings)
+
+- (NSString *)_sybModelMakeInstanceVarName {
+ if ([self length] == 0)
+ return @"";
+ else {
+ unsigned clen = 0;
+ char *s = NULL;
+ unsigned cnt, cnt2;
+
+ clen = [self cStringLength];
+ s = objc_atomic_malloc(clen + 5);
+
+ [self getCString:s maxLength:clen];
+
+ for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) {
+ if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = toupper(s[cnt + 1]);
+ cnt++;
+ }
+ else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = s[cnt];
+ cnt++;
+ cnt2++;
+ s[cnt2] = toupper(s[cnt]);
+ }
+ else
+ s[cnt2] = tolower(s[cnt]);
+ }
+ s[cnt2] = '\0';
+
+ return AUTORELEASE([[NSString alloc] initWithCStringNoCopy:s length:strlen(s) freeWhenDone:YES]);
+ }
+}
+
+- (NSString *)_sybModelMakeClassName {
+ if ([self length] == 0)
+ return @"";
+ else {
+ unsigned clen = 0;
+ char *s = NULL;
+ unsigned cnt, cnt2;
+
+ clen = [self cStringLength];
+ s = objc_atomic_malloc(clen + 1);
+
+ [self getCString:s maxLength:clen];
+
+ for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) {
+ if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = toupper(s[cnt + 1]);
+ cnt++;
+ }
+ else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = s[cnt];
+ cnt++;
+ cnt2++;
+ s[cnt2] = toupper(s[cnt]);
+ }
+ else
+ s[cnt2] = tolower(s[cnt]);
+ }
+ s[cnt2] = '\0';
+
+ s[0] = toupper(s[0]);
+
+ return AUTORELEASE([[NSString alloc] initWithCStringNoCopy:s length:s?strlen(s):0 freeWhenDone:YES]);
+ }
+}
+
+- (NSString *)_sybStringWithCapitalizedFirstChar {
+ NSCharacterSet *upperSet = [NSCharacterSet uppercaseLetterCharacterSet];
+
+ if ([self length] == 0)
+ return @"";
+ else if ([upperSet characterIsMember:[self characterAtIndex:0]])
+ return AUTORELEASE([self copy]);
+ else {
+ NSMutableString *str = [NSMutableString stringWithCapacity:[self length]];
+
+ [str appendString:[[self substringToIndex:1] uppercaseString]];
+ [str appendString:[self substringFromIndex:1]];
+
+ return AUTORELEASE([str copy]);
+ }
+}
+
+- (NSString *)_sybStripEndSpaces {
+ if ([self length] > 0) {
+ NSCharacterSet *spaceSet = [NSCharacterSet whitespaceCharacterSet];
+ NSMutableString *str = [NSMutableString stringWithCapacity:[self length]];
+ IMP charAtIndex;
+ NSRange range;
+
+ charAtIndex = [self methodForSelector:@selector(characterAtIndex:)];
+ range.length = 0;
+
+ for (range.location = ([self length] - 1);
+ range.location >= 0;
+ range.location++, range.length++) {
+ unichar c;
+
+ c = (unichar)(int)charAtIndex(self, @selector(characterAtIndex:),
+ range.location);
+ if (![spaceSet characterIsMember:c])
+ break;
+ }
+
+ if (range.length > 0) {
+ [str appendString:self];
+ [str deleteCharactersInRange:range];
+ return AUTORELEASE([str copy]);
+ }
+ }
+ return AUTORELEASE([self copy]);
+}
+
+@end
+
+void __link_NSStringFB() {
+ // used to force linking of object file
+ __link_NSStringFB();
+}
--- /dev/null
+# $Id: README 1 2004-08-20 10:38:46Z znek $
+
+FrontBase GDL database adaptor
+
+This package contains a GDL database adaptor for the FrontBase database
+(www.frontbase.com). It was written with a lot of help from the people
+at Frontline Software.
+
+If you have any fixes, questions or patches to this adaptor, contact me at
+
+ helge.hess@mdlink.de
+
+Notably the development of this adaptor was supported by
+
+ MDlink online service center GmbH
+ http://www.mdlink.de/
+
+Helge Hess, helge.hess@mdlink.de
+1999-11-03
--- /dev/null
+# $Id: Version 1 2004-08-20 10:38:46Z znek $
+
+SUBMINOR_VERSION:=2
--- /dev/null
+#!/bin/sh
+
+if test -d ./fb2/$1/$2/include/FBCAccess; then
+ echo "yes"
+else
+ echo "no"
+fi
--- /dev/null
+/*
+ common.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge.hess@mdlink.de)
+
+ This file is part of the FB Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: common.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___FB_common_H___
+#define ___FB_common_H___
+
+#import <objc/objc-api.h>
+
+#if LIB_FOUNDATION_BOEHM_GC
+# include <objc/gc.h>
+# include <objc/gc_typed.h>
+# include <extensions/GarbageCollector.h>
+#endif
+
+#import <Foundation/Foundation.h>
+
+
+#if !LIB_FOUNDATION_LIBRARY
+# import <FoundationExt/NSObjectMacros.h>
+# import <FoundationExt/FoundationException.h>
+# import <FoundationExt/NSCoderExceptions.h>
+# import <FoundationExt/NSException.h>
+# import <FoundationExt/GeneralExceptions.h>
+# import <FoundationExt/objc-api.h>
+# import <FoundationExt/objc-runtime.h>
+#else
+# import <Foundation/exceptions/GeneralExceptions.h>
+#endif
+
+#import <GDLAccess/EOAccess.h>
+
+#import "FBException.h"
+#import "FBSQLExpression.h"
+
+#import "FBChannel.h"
+#import "FBContext.h"
+#import "FrontBase2Adaptor.h"
+
+#import "FBChannel+Model.h"
+#import "FBValues.h"
+#import "EOAttribute+FB.h"
+#import "NSString+FB.h"
+
+#endif
--- /dev/null
+{
+ userName = "test";
+ databaseName = "helgetest";
+ hostName = "localhost";
+}
--- /dev/null
+// $Id: fbtest.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/Foundation.h>
+#import <NGExtensions/NGExtensions.h>
+#import <GDLAccess/EOAccess.h>
+//#include "FBAdaptor.h"
+
+#define ADAPTOR_LEVEL 1
+
+unsigned txRepeatCount = 1;
+
+static int doAdPersTest1(EOModel *m,EOAdaptorContext *ctx, EOAdaptorChannel *ch) {
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ EOEntity *e;
+ EOSQLQualifier *q;
+ NSArray *attrs;
+ id record;
+
+ /* fetch some person records */
+
+ e = [m entityNamed:@"Person"];
+ q = [e qualifier];
+ attrs = [e attributes];
+#if 0
+ NSLog(@"entity: %@", e);
+ NSLog(@"qual: %@", q);
+ NSLog(@"attrs: %@", attrs);
+#endif
+
+ if (attrs == nil) {
+ NSLog(@"missing Person attributes in entity %@ !!!", e);
+ }
+
+ {
+ NSCalendarDate *start;
+ unsigned count, i;
+
+ q = [[EOSQLQualifier alloc] initWithEntity:e
+ qualifierFormat:@"%A=5010", @"personId"];
+
+ start = [NSCalendarDate date];
+
+ count = 1;
+ for (i = 0; i < count; i++) {
+ //NSCAssert(attrs, @"missing attributes !!!");
+
+ if ([ch selectAttributes:attrs
+ describedByQualifier:q
+ fetchOrder:nil
+ lock:NO]) {
+ while ((record = [ch fetchAttributes:attrs withZone:nil])) {
+#if 1
+ NSLog(@"fetched %@ id %@",
+ [record valueForKey:@"pname"],
+ [record valueForKey:@"personId"]);
+#endif
+ }
+ }
+ else {
+ NSLog(@"select failed ...");
+ break;
+ }
+ }
+ NSLog(@"duration: count %i %.3fs", count,
+ [[NSCalendarDate date] timeIntervalSinceDate:start]);
+ }
+
+ RELEASE(pool);
+ return 1;
+}
+
+static int doAdTest1(EOModel *m,EOAdaptorContext *ctx, EOAdaptorChannel *ch) {
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+#endif
+ EOEntity *e;
+ EOSQLQualifier *q;
+ NSArray *attrs;
+
+ /* fetch some team records */
+
+ e = [m entityNamed:@"Team"];
+ q = [e qualifier];
+ attrs = [e attributes];
+
+ if ([ch selectAttributes:attrs
+ describedByQualifier:q
+ fetchOrder:nil
+ lock:NO]) {
+ NSDictionary *record;
+
+ while ((record = [ch fetchAttributes:attrs withZone:nil])) {
+ NSLog(@"fetched %@ birthday %@",
+ [record valueForKey:@"description"],
+ [record valueForKey:@"companyId"]);
+ }
+ }
+
+ /* do some update */
+
+ e = [m entityNamed:@"Person"];
+ attrs = [e attributes];
+ q = [[EOSQLQualifier alloc] initWithEntity:e
+ qualifierFormat:@"%A='helge'", @"login"];
+
+ q = AUTORELEASE(q);
+
+ if ([ch selectAttributes:attrs
+ describedByQualifier:q
+ fetchOrder:nil
+ lock:NO]) {
+ NSDictionary *record;
+
+ while ((record = [ch fetchAttributes:attrs withZone:nil]))
+ ;
+ }
+ #if 0
+ /* fetch some expr */
+
+ if (expr) {
+ if ([ch evaluateExpression:expr]) {
+ NSDictionary *record;
+
+ attrs = [ch describeResults];
+ //NSLog(@"results: %@", attrs);
+
+ while ((record = [ch fetchAttributes:attrs withZone:nil]))
+ NSLog(@"fetched %@", record);
+ }
+ }
+ #endif
+
+ RELEASE(pool);
+ }
+ return 1;
+}
+
+static void runAdTests(NSDictionary *conDict) {
+ EOModel *m;
+ EOAdaptor *a;
+ EOAdaptorContext *ctx;
+ EOAdaptorChannel *ch;
+ NSString *expr;
+
+ a = [EOAdaptor adaptorWithName:@"FrontBase2"];
+ //a = [[FrontBaseAdaptor alloc] initWithName:@"FrontBase"];
+ [a setConnectionDictionary:conDict];
+ NSLog(@"got adaptor[%@] %@", NSStringFromClass([a class]), a);
+
+ ctx = [a createAdaptorContext];
+ ch = [ctx createAdaptorChannel];
+
+ m = AUTORELEASE([[EOModel alloc] initWithContentsOfFile:@"test.eomodel"]);
+ [a setModel:m];
+ [a setConnectionDictionary:conDict];
+
+ expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"];
+
+ NSLog(@"opening channel ..");
+
+ //[ch setDebugEnabled:NO];
+
+ if ([ch openChannel]) {
+ int txi;
+ NSLog(@"channel is open");
+
+ for (txi = 0; txi < txRepeatCount; txi++) {
+ if ([ctx beginTransaction]) {
+ NSLog(@"began tx (%i) ..", txi);
+
+ /* do something */
+ if (!doAdPersTest1(m, ctx, ch))
+ break;
+
+ NSLog(@"committing tx ..");
+ if ([ctx commitTransaction])
+ NSLog(@" could commit.");
+ else
+ NSLog(@" commit failed.");
+ }
+ else {
+ NSLog(@"tx open failed ..");
+ }
+ }
+
+ NSLog(@"closing channel ..");
+ [ch closeChannel];
+ }
+ else {
+ NSLog(@"open channel failed ...");
+ }
+}
+
+static void runDbTests(NSDictionary *conDict) {
+ EOModel *m;
+ EOAdaptor *a;
+ EODatabase *db;
+ EODatabaseContext *ctx;
+ EODatabaseChannel *ch;
+ NSString *expr;
+
+ a = [EOAdaptor adaptorWithName:@"FrontBase2"];
+ //a = [[FrontBaseAdaptor alloc] initWithName:@"FrontBase"];
+ [a setConnectionDictionary:conDict];
+ NSLog(@"got adaptor[%@] %@", NSStringFromClass([a class]), a);
+
+ db = [[EODatabase alloc] initWithAdaptor:a];
+ ctx = [db createContext];
+ ch = [ctx createChannel];
+
+ m = AUTORELEASE([[EOModel alloc] initWithContentsOfFile:@"test.eomodel"]);
+ [a setModel:m];
+ [a setConnectionDictionary:conDict];
+
+ expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"];
+
+ NSLog(@"opening channel ..");
+
+ if ([ch openChannel]) {
+ int txi;
+ NSLog(@"channel is open");
+
+ for (txi = 0; txi < txRepeatCount; txi++) {
+ if ([(EOAdaptorContext *)ctx beginTransaction]) {
+ NSLog(@"began tx ..");
+
+ /* do something */
+ {
+#if !LIB_FOUNDATION_BOEHM_GC
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+#endif
+ EOEntity *e;
+ EOSQLQualifier *q;
+ NSArray *attrs;
+ id record;
+
+ /* fetch some person records */
+
+ e = [m entityNamed:@"Person"];
+ q = [e qualifier];
+ attrs = [e attributes];
+
+ if ([ch selectObjectsDescribedByQualifier:q fetchOrder:nil]) {
+ while ((record = [ch fetchWithZone:nil])) {
+ NSLog(@"fetched %@ birthday %@",
+ [record valueForKey:@"description"],
+ [record valueForKey:@"companyId"]);
+ }
+ }
+
+ /* fetch some team records */
+
+ e = [m entityNamed:@"Team"];
+ q = [e qualifier];
+ attrs = [e attributes];
+
+ /* do some update */
+
+ e = [m entityNamed:@"Person"];
+ attrs = [e attributes];
+ q = [[EOSQLQualifier alloc] initWithEntity:e
+ qualifierFormat:@"%A='helge'", @"login"];
+
+ q = AUTORELEASE(q);
+
+ RELEASE(pool);
+ }
+
+ NSLog(@"committing tx ..");
+ if ([ctx commitTransaction])
+ NSLog(@" could commit.");
+ else
+ NSLog(@" commit failed.");
+ }
+ }
+
+ NSLog(@"closing channel ..");
+ [ch closeChannel];
+ }
+ else {
+ NSLog(@"open channel failed ...");
+ }
+}
+
+int main(int argc, char **argv, char **env) {
+ NSAutoreleasePool *pool;
+ NSDictionary *conDict;
+
+ pool = [[NSAutoreleasePool alloc] init];
+
+#if LIB_FOUNDATION_LIBRARY
+ [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+ conDict = [NSDictionary dictionaryWithContentsOfFile:@"condict.plist"];
+
+ runAdTests(conDict);
+
+ RELEASE(pool);
+ return 0;
+}
--- /dev/null
+#!/usr/bin/env python
+# $Id: fbtest.py 2 2004-08-20 10:48:47Z znek $
+
+from Foundation import *
+from eoaccess import *
+
+conDict = { 'userName': "skyrix",
+ 'databaseName': "Skyrix",
+ 'hostName': "inster" }
+
+adaptor = EOAdaptor(name='FrontBase2')
+adaptor.setConnectionDictionary(conDict)
+print "got adaptor ", adaptor.invoke0("class");
+
+ctx = adaptor.createAdaptorContext()
+ch = ctx.createAdaptorChannel()
+
+model = EOModel(contentsOfFile='test.eomodel')
+adaptor.setModel(model)
+adaptor.setConnectionDictionary(conDict)
+
+ch.setDebugEnabled(YES)
+
+if ch.openChannel():
+ print "channel is open"
+
+ if ctx.beginTransaction():
+ print "began tx .."
+
+ pool = NSAutoreleasePool()
+
+ e = model.entityNamed('Person')
+ q = e.qualifier()
+ attrs = e.attributes()
+
+ if ch.selectAttributes(attrs, q):
+ record = ch.fetchAttributes(attrs)
+ while record is not None:
+ print " login=%(login)s name=%(name)s bday=%(birthday)s" % \
+ record
+ record = ch.fetchAttributes(attrs)
+
+ del pool
+
+ pool = NSAutoreleasePool()
+
+ e = model.entityNamed('Person')
+ attrs = e.attributes()
+ q = EOKeyValueQualifier('login', EOQualifierOperatorEqual, 'helge')
+ q = q.sqlQualifierForEntity(e)
+
+ if ch.selectAttributes(attrs, q):
+ record = ch.fetchAttributes(attrs)
+ print " login=%(login)s name=%(name)s bday=%(birthday)s" % \
+ record
+ ch.cancelFetch()
+
+ date = NSCalendarDate()
+ print "date in localtime:", date
+ date.setTimeZone(NSTimeZone("PST"))
+ print "date in pacific time:", date
+
+ record['birthday'] = date
+ print " login=%(login)s name=%(name)s bday=%(birthday)s" % record
+
+ if ch.updateRow(record, q):
+ print "did update .."
+ else:
+ print "update failed .."
+
+ if ch.selectAttributes(attrs, q):
+ nrecord = ch.fetchAttributes(attrs)
+ print " login=%(login)s name=%(name)s bday=%(birthday)s" % \
+ nrecord
+ print nrecord['birthday'].__class__
+ ch.cancelFetch()
+
+ del pool
+
+ ctx.rollbackTransaction()
+ else:
+ print "couldn't begin tx."
+
+ ch.closeChannel()
+else:
+ print "couldn't open channel."
+
--- /dev/null
+{
+ EOModelVersion = 1;
+ adaptorClassName = FrontBase2Adaptor;
+ adaptorName = FrontBase;
+
+ pkeyGeneratorDictionary = {
+ newKeyExpression = "SELECT UNIQUE FROM key_generator";
+ };
+
+ entities = (
+ {
+ externalName = person;
+ className = EOGenericRecord;
+ name = Person;
+ attributes = (
+ {
+ valueClassName = NSNumber;
+ columnName = person_id;
+ name = personId;
+ valueType = i;
+ externalType = int;
+ },
+ {
+ valueClassName = NSNumber;
+ columnName = blah;
+ name = blah;
+ valueType = i;
+ externalType = int;
+ },
+ {
+ valueClassName = NSString;
+ columnName = pname;
+ name = pname;
+ externalType = varchar;
+ },
+ {
+ valueClassName = NSString;
+ columnName = street;
+ name = street;
+ externalType = varchar;
+ },
+ {
+ valueClassName = NSString;
+ columnName = city;
+ name = city;
+ externalType = varchar;
+ }
+ );
+ classProperties = (
+ personId,blah,pname,street,city
+ );
+ relationships = (
+ );
+ primaryKeyAttributes = ( personId );
+ attributesUsedForLocking = (
+ personId
+ );
+ }
+ );
+}
--- /dev/null
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
--- /dev/null
+2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+
+ * moved from ThirdParty to SOPE/sope-gdl1 (v1.0.32)
+
+2004-06-29 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.31
+
+ * EOAdaptorChannel.m: fixed a bug in the transaction check introduced
+ in v1.0.29 - resulted in OGo bug #824, #825
+
+ * EODatabaseChannel.m: use new "X" adaptor methods
+
+ * GNUmakefile.preamble: added include path to SOPE/skyrix-core for
+ "inline" compilation (v1.0.30)
+
+2004-06-28 Helge Hess <helge.hess@opengroupware.org>
+
+ * EOAdaptorChannel.[hm]: added more "X" methods which do not raise
+ exceptions (v1.0.29)
+
+ * EOAdaptorChannel.m: added new method -evaluateExpressionX: which
+ returns the exception instead of raising it. It returns
+ @"EOEvaluationError" if the -evaluateExpression: returned NO without
+ raising an exception. It is recommended that adaptor classes
+ implement -evaluateExpression: using -evaluateExpressionX:, not the
+ other way around (v1.0.28)
+
+2004-06-27 Helge Hess <helge.hess@opengroupware.org>
+
+ * EOModel.m: minor code cleanups (v1.0.27)
+
+2004-06-21 Helge Hess <helge.hess@opengroupware.org>
+
+ * EOModel.m: some code cleanups, improved description (v1.0.26)
+
+2004-06-06 Helge Hess <helge.hess@opengroupware.org>
+
+ * fixed Xcode compilation with embedded FoundationExt classes (v1.0.25)
+
+2004-05-14 Helge Hess <helge@developer.opengroupware.org>
+
+ * EOAdaptorDataSource.m: removed some ==YES comparisons, minor cleanups
+ (v1.0.24)
+
+2004-03-14 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.23
+
+ * EOSQLQualifier.m: improved -description method
+
+ * EOSQLExpression.m: moved EOSelectSQLExpression to separate file,
+ added a -description method, various minor code cleanups
+
+ * EOExpressionArray.m: added a -description method, minor cleanups
+
+ * EOAdaptorChannel.m: minor code cleanups
+
+ * EODatabaseContext.m: removed registration for
+ EOCooperatingObjectStoreNeeded notification (solves an issue with
+ gstep-base)
+
+2004-03-09 Helge Hess <helge.hess@opengroupware.org>
+
+ * EOAdaptorChannel.m, EOAdaptorDataSource.m, EOAttribute.m,
+ EODatabase.m, EOEntity.m, EOEntityClassDescription.m,
+ EOQualifier+SQL.m, EOSQLExpression.m, common.h, EOQualifierScanner.h:
+ various subminor fixes for compilation against gstep-base (v1.0.22)
+
+2004-02-12 Helge Hess <helge.hess@opengroupware.org>
+
+ * EODatabaseChannel.m: only check for GC objects on libFoundation
+ (v1.0.21)
+
+2004-01-29 Helge Hess <helge.hess@skyrix.com>
+
+ * EORecordDictionary.m: disabled a profiling log (v1.0.20)
+
+2004-01-07 Helge Hess <helge@groove.local>
+
+ * some tweaks for Xcode compilation (v1.0.19)
+
+2004-01-04 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.18
+
+ * more tweaks to makefiles and source, now seems to compile fine on
+ MacOSX
+
+ * added FoundationExt subproject containing the necessary classes from
+ the extensions library, that is, the FormatScanner,
+ PrintfFormatScanner and DefaultScannerHandler
+
+2004-01-03 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.17
+
+ * EORecordDictionary.m: cache -hash and -isEqual selector in
+ objectForKey:
+
+ * various changes to make gnustep-db compile on MacOSX (eg do not use
+ InvalidArgumentException class but rather NSInvalidArgumentException
+ exception name, etc)
+
+2003-12-29 Helge Hess <helge.hess@opengroupware.org>
+
+ * EORecordDictionary.m(dealloc): cache release method of dict key,
+ which is basically always an NSString, also cache empty dictionary
+ (v1.0.16)
+
+2003-10-20 Helge Hess <helge.hess@skyrix.com>
+
+ * v1.0.15
+
+ * common.h: do not use zones for memory allocation (read: speedup)
+
+ * removed support for Boehm GC, makes code much more readable and
+ shorter (and isn't used in OGo anyway ...)
+
+ * removed some warnings, some FoundationExt cleanups
+
+ * EOExpressionArray.h: does not inherit from GCObject and use
+ GCMutableArray anymore (replaced with NSObject and NSMutableArray)
+
+ * EODatabaseContext.m: removed some unused methods
+
+ * removed some GCObject dependency
+
+ * EODatabaseChannel.m: removed some unused methods
+
+Wed Oct 15 16:26:50 2003 Jan Reichmann <jr@skyrix.com>
+
+ * EOModel.m: initialize model name with the filename which contains the model
+ (*.eomodel) (v1.0.14)
+
+Sun Sep 07 00:30:59 2003 Marcus Mueller <znek@mulle-kybernetik.com>
+
+ * GNUmakefile: reordered autodoc target
+
+Mon Jul 14 14:07:22 2003 Jan Reichmann <jr@skyrix.com>
+
+ * fixed license entries (v1.0.13)
+
+Fri Jul 4 19:15:35 2003 Helge Hess <helge.hess@skyrix.com>
+
+ * imported into OpenGroupware.org (v1.0.11)
--- /dev/null
+// $Id: EOAccess.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __GDLAccess_H__
+#define __GDLAccess_H__
+
+#import <GDLAccess/EODatabase.h>
+#import <GDLAccess/EODatabaseChannel.h>
+#import <GDLAccess/EODatabaseContext.h>
+
+#import <GDLAccess/EOAdaptor.h>
+#import <GDLAccess/EOAdaptorChannel.h>
+#import <GDLAccess/EOAdaptorContext.h>
+#import <GDLAccess/EOAttribute.h>
+#import <GDLAccess/EOAttributeOrdering.h>
+#import <GDLAccess/EOCustomValues.h>
+#import <GDLAccess/EODatabase.h>
+#import <GDLAccess/EODatabaseChannel.h>
+#import <GDLAccess/EODatabaseContext.h>
+#import <GDLAccess/EOEntity.h>
+#import <GDLAccess/EOExpressionArray.h>
+#import <GDLAccess/EOFExceptions.h>
+#import <GDLAccess/EOGenericRecord.h>
+#import <GDLAccess/EOKeySortOrdering.h>
+#import <GDLAccess/EOModel.h>
+#import <GDLAccess/EOObjectUniquer.h>
+#import <GDLAccess/EOPrimaryKeyDictionary.h>
+#import <GDLAccess/EOQuotedExpression.h>
+#import <GDLAccess/EORelationship.h>
+#import <GDLAccess/EOSQLExpression.h>
+#import <GDLAccess/EOSQLQualifier.h>
+#import <GDLAccess/EOAdaptorChannel+Attributes.h>
+#import <GDLAccess/EOAdaptorDataSource.h>
+#import <GDLAccess/EOAdaptorGlobalID.h>
+
+#import <EOControl/EOGenericRecord.h>
+#import <EOControl/EOKeyValueCoding.h>
+
+// Kit class
+
+@interface GDLAccess : NSObject
+@end
+
+#endif /* __GDLAccess_H__ */
--- /dev/null
+/*
+ EOAdaptor.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOAdaptor_h__
+#define __EOAdaptor_h__
+
+#import <Foundation/NSObject.h>
+
+@class NSMutableArray, NSArray;
+@class NSDictionary;
+@class NSString;
+
+@class EOModel;
+@class EOAttribute;
+@class EOAdaptorContext;
+
+/* The EOAdaptor class could be overriden for a concrete database adaptor.
+ You have to override only those methods marked in this header with
+ `override'.
+*/
+
+/* Don't make EOAdaptor* classes garbage collectable because we want to make
+ the instances release the database allocated resources immediately when they
+ receive the -release message. */
+
+@interface EOAdaptor : NSObject
+{
+@protected
+ EOModel *model;
+ NSString *name;
+ NSDictionary *connectionDictionary;
+ NSDictionary *pkeyGeneratorDictionary;
+ NSMutableArray *contexts; // values with contexts
+ id delegate; // not retained
+
+ /* Flags used to check if the delegate responds to several messages */
+ BOOL delegateWillReportError:1;
+}
+
+/* Creating an EOAdaptor */
++ (id)adaptorWithModel:(EOModel *)aModel;
++ (id)adaptorWithName:(NSString *)aName;
+- (id)initWithName:(NSString *)aName;
+
+/* Getting an adaptor's name */
+- (NSString*)name;
+
+/* Setting connection information */
+- (void)setConnectionDictionary:(NSDictionary*)aDictionary;
+- (NSDictionary*)connectionDictionary;
+- (BOOL)hasValidConnectionDictionary; // override
+
+/* Setting pkey generation info */
+- (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary;
+- (NSDictionary*)pkeyGeneratorDictionary;
+
+/* Setting the model */
+- (void)setModel:(EOModel*)aModel;
+- (EOModel*)model;
+
+/* Creating and removing an adaptor context */
+- (EOAdaptorContext*)createAdaptorContext; // override
+- (NSArray *)contexts;
+
+/* Checking connection status */
+- (BOOL)hasOpenChannels;
+
+/* Getting adaptor-specific information */
+- (Class)expressionClass; // override
+- (Class)adaptorContextClass; // override
+- (Class)adaptorChannelClass; // override
+- (BOOL)isValidQualifierType:(NSString*)aTypeName; // override
+
+/* Formatting SQL */
+- (id)formatAttribute:(EOAttribute*)attribute; // override
+- (id)formatValue:value forAttribute:(EOAttribute*)attribute; // override
+
+/* Reporting errors */
+- (void)reportError:(NSString*)anError;
+
+/* Setting the delegate */
+- (id)delegate;
+- (void)setDelegate:(id)aDelegate;
+
+@end /* EOAdaptor */
+
+
+@interface EOAdaptor(Private)
+- (void)contextDidInit:(id)aContext;
+- (void)contextWillDealloc:(id)aContext;
+@end
+
+
+@interface NSObject(EOAdaptorDelegate)
+
+- (BOOL)adaptor:(EOAdaptor*)anAdaptor willReportError:(NSString*)anError;
+
+@end /* NSObject(EOAdaptorDelegate) */
+
+@interface EOAdaptor(MDlinkExtensions)
+- (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName;
+- (NSString *)lowerExpressionForTextAttributeNamed:(NSString *)_attrName;
+- (NSString *)expressionForTextValue:(id)_value;
+- (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)attribute;
+@end
+
+@interface EOAdaptor(EOF2Additions)
+
+- (BOOL)canServiceModel:(EOModel *)_model;
+
+@end
+
+#endif /* __EOAdaptor_h__*/
--- /dev/null
+//$Id: EOAdaptorChannel+Attributes.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOAdaptorChannel_Attributes_h__
+#define __EOAdaptorChannel_Attributes_h__
+
+@class NSString, NSArray;
+
+#import <GDLAccess/EOAdaptorChannel.h>
+
+@interface EOAdaptorChannel(Attributes)
+
+- (NSArray *)attributesForTableName:(NSString *)_tableName;
+- (NSArray *)primaryKeyAttributesForTableName:(NSString *)_tableName;
+
+@end
+
+#endif /* __EOAdaptorChannel_Attributes_h__ */
--- /dev/null
+/*
+ EOAdaptorChannel.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOAdaptorChannel_h__
+#define __EOAdaptorChannel_h__
+
+#import <Foundation/NSObject.h>
+
+@class NSArray, NSMutableArray, NSDictionary, NSMutableDictionary, NSString;
+@class NSMutableString, NSCalendarDate, NSException;
+
+@class EOModel, EOEntity, EOAttribute, EOSQLQualifier, EOAdaptorContext;
+
+/*
+ The EOAdaptorChannel class can be subclassed in a database adaptor. You have
+ to override only those methods marked in this header with `override'.
+*/
+
+@interface EOAdaptorChannel : NSObject
+{
+@protected
+ EOAdaptorContext *adaptorContext;
+ id delegate; // not retained
+
+ /* Flags that determine the state of the adaptor */
+ BOOL isFetchInProgress;
+ BOOL isOpen;
+ BOOL debugEnabled;
+
+ /* Flags used to check if the delegate responds to several messages */
+ struct {
+ BOOL willInsertRow:1;
+ BOOL didInsertRow:1;
+ BOOL willUpdateRow:1;
+ BOOL didUpdateRow:1;
+ BOOL willDeleteRows:1;
+ BOOL didDeleteRows:1;
+ BOOL willSelectAttributes:1;
+ BOOL didSelectAttributes:1;
+ BOOL willFetchAttributes:1;
+ BOOL didFetchAttributes:1;
+ BOOL didChangeResultSet:1;
+ BOOL didFinishFetching:1;
+ BOOL willEvaluateExpression:1;
+ BOOL didEvaluateExpression:1;
+ } delegateRespondsTo;
+}
+
++ (NSCalendarDate*)dateForAttribute:(EOAttribute*)attr
+ year:(int)year month:(unsigned)month day:(unsigned)day
+ hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second
+ zone:(NSZone*)zone;
+
+/* Initializing an adaptor context */
+- (id)initWithAdaptorContext:(EOAdaptorContext*)adaptorContext;
+
+/* Getting the adaptor context */
+- (EOAdaptorContext*)adaptorContext;
+
+/* Opening and closing a channel */
+- (BOOL)isOpen;
+- (BOOL)openChannel;
+- (void)closeChannel;
+
+/* Modifying rows, new world methods */
+- (NSException *)insertRowX:(NSDictionary *)_row forEntity:(EOEntity *)_entity;
+- (NSException *)updateRowX:(NSDictionary*)aRow
+ describedByQualifier:(EOSQLQualifier*)aQualifier;
+- (NSException *)deleteRowsDescribedByQualifierX:(EOSQLQualifier*)aQualifier;
+
+/* Modifying rows, old world methods (DEPRECATED) */
+- (BOOL)insertRow:(NSDictionary *)aRow forEntity:(EOEntity *)anEntity;
+- (BOOL)updateRow:(NSDictionary *)aRow
+ describedByQualifier:(EOSQLQualifier *)aQualifier;
+- (BOOL)deleteRowsDescribedByQualifier:(EOSQLQualifier *)aQualifier;
+
+/* Fetching rows */
+- (BOOL)selectAttributes:(NSArray*)attributes
+ describedByQualifier:(EOSQLQualifier*)aQualifier
+ fetchOrder:(NSArray*)aFetchOrder
+ lock:(BOOL)aLockFlag;
+- (NSArray*)describeResults; // override
+- (NSMutableDictionary*)fetchAttributes:(NSArray*)attributes
+ withZone:(NSZone*)zone;
+- (BOOL)isFetchInProgress;
+- (void)cancelFetch; // override
+- (NSMutableDictionary*)dictionaryWithObjects:(id*)objects
+ forAttributes:(NSArray*)attributes zone:(NSZone*)zone;
+- (NSMutableDictionary*)primaryFetchAttributes:(NSArray*)attributes
+ withZone:(NSZone*)zone; // override
+
+/* Sending SQL to the server */
+- (BOOL)evaluateExpression:(NSString *)_anExpression; // override
+- (NSException *)evaluateExpressionX:(NSString*)_sql;
+
+/* Getting schema information */
+- (EOModel*)describeModelWithTableNames:(NSArray*)tableNames; // override
+- (NSArray*)describeTableNames; // override
+- (BOOL)readTypesForEntity:(EOEntity*)anEntity; // override
+- (BOOL)readTypeForAttribute:(EOAttribute*)anAttribute; // override
+
+/* Debugging */
+- (void)setDebugEnabled:(BOOL)flag;
+- (BOOL)isDebugEnabled;
+
+/* Setting the channel's delegate */
+- (id)delegate;
+- (void)setDelegate:aDelegate;
+
+@end /* EOAdaptorChannel*/
+
+@interface EOAdaptorChannel(PrimaryKeyGeneration) // new in EOF2
+
+- (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity;
+
+@end
+
+@class EOEntity, EOFetchSpecification;
+
+@interface EOAdaptorChannel(EOF2Additions)
+
+- (void)selectAttributes:(NSArray *)_attributes
+ fetchSpecification:(EOFetchSpecification *)_fspec
+ lock:(BOOL)_flag
+ entity:(EOEntity *)_entity;
+
+- (void)setAttributesToFetch:(NSArray *)_attributes;
+- (NSArray *)attributesToFetch;
+
+- (NSMutableDictionary *)fetchRowWithZone:(NSZone *)_zone;
+
+@end
+
+#import <GDLAccess/EODelegateResponse.h>
+
+@interface NSObject(EOAdaptorChannelDelegation)
+
+- (EODelegateResponse)adaptorChannel:aChannel
+ willInsertRow:(NSMutableDictionary*)aRow
+ forEntity:(EOEntity*)anEntity;
+- (void)adaptorChannel:channel
+ didInsertRow:(NSDictionary*)aRow
+ forEntity:(EOEntity*)anEntity;
+- (EODelegateResponse)adaptorChannel:aChannel
+ willUpdateRow:(NSMutableDictionary*)aRow
+ describedByQualifier:(EOSQLQualifier*)aQualifier;
+- (void)adaptorChannel:aChannel
+ didUpdateRow:(NSDictionary*)aRow
+ describedByQualifier:(EOSQLQualifier*)aQualifier;
+- (EODelegateResponse)adaptorChannel:aChannel
+ willDeleteRowsDescribedByQualifier:(EOSQLQualifier*)aQualifier;
+- (void)adaptorChannel:aChannel
+ didDeleteRowsDescribedByQualifier:(EOSQLQualifier*)aQualifier;
+- (EODelegateResponse)adaptorChannel:aChannel
+ willSelectAttributes:(NSMutableArray*)attributes
+ describedByQualifier:(EOSQLQualifier*)aQualifier
+ fetchOrder:(NSMutableArray*)aFetchOrder
+ lock:(BOOL)aLockFlag;
+- (void)adaptorChannel:aChannel
+ didSelectAttributes:(NSArray*)attributes
+ describedByQualifier:(EOSQLQualifier*)aQualifier
+ fetchOrder:(NSArray*)aFetchOrder
+ lock:(BOOL)aLockFlag;
+- (NSMutableDictionary*)adaptorChannel:aChannel
+ willFetchAttributes:(NSArray*)attributes
+ withZone:(NSZone*)zone;
+- (NSMutableDictionary*)adaptorChannel:aChannel
+ didFetchAttributes:(NSMutableDictionary*)attributes
+ withZone:(NSZone*)zone;
+- (void)adaptorChannelDidChangeResultSet:aChannel;
+- (void)adaptorChannelDidFinishFetching:aChannel;
+- (EODelegateResponse)adaptorChannel:aChannel
+ willEvaluateExpression:(NSMutableString*)anExpression;
+- (void)adaptorChannel:aChannel
+ didEvaluateExpression:(NSString*)anExpression;
+
+@end /* NSObject(EOAdaptorChannelDelegation) */
+
+#endif /* __EOAdaptorChannel_h__ */
--- /dev/null
+/*
+ EOAdaptorContext.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOAdaptorContext_h__
+#define __EOAdaptorContext_h__
+
+#import <Foundation/NSObject.h>
+
+@class NSArray, NSMutableArray;
+
+@class EOAdaptor;
+@class EOAdaptorChannel;
+
+/* The EOAdaptorContext class could be overriden for a concrete database
+ adaptor. You have to override only those methods marked in this header
+ with `override'.
+*/
+
+@interface EOAdaptorContext : NSObject
+{
+ EOAdaptor *adaptor;
+ NSMutableArray *channels; // values with channels
+ id delegate; // not retained
+ int transactionNestingLevel;
+
+ /* Flags used to check if the delegate responds to several messages */
+ struct {
+ BOOL willBegin:1;
+ BOOL didBegin:1;
+ BOOL willCommit:1;
+ BOOL didCommit:1;
+ BOOL willRollback:1;
+ BOOL didRollback:1;
+ } delegateRespondsTo;
+}
+
+/* Initializing an adaptor context */
+- (id)initWithAdaptor:(EOAdaptor*)adaptor;
+
+/* Setting and getting the adaptor */
+- (EOAdaptor*)adaptor;
+
+/* Creating a new channel */
+- (EOAdaptorChannel*)createAdaptorChannel; // override
+- (NSArray *)channels;
+
+/* Checking connection status */
+- (BOOL)hasOpenChannels;
+
+/* Finding open channels */
+- (BOOL)hasBusyChannels;
+
+/* Controlling transactions */
+- (BOOL)beginTransaction;
+- (BOOL)commitTransaction;
+- (BOOL)rollbackTransaction;
+
+/* Notifying of other transactions */
+- (void)transactionDidBegin;
+- (void)transactionDidCommit;
+- (void)transactionDidRollback;
+
+/* Nesting transactions */
+- (BOOL)canNestTransactions; // override, deprecated
+- (unsigned)transactionNestingLevel; // deprecated
+- (BOOL)hasOpenTransaction; // new in WO 4.5
+
+/* Setting the delegate */
+- (id)delegate;
+- (void)setDelegate:(id)aDelegate;
+
+/* Primary methods that control the transactions. This methods dont't call the
+ delegate. You should implement these methods instead of the similar ones but
+ without the `primary' prefix. */
+- (BOOL)primaryBeginTransaction; // override
+- (BOOL)primaryCommitTransaction; // override
+- (BOOL)primaryRollbackTransaction; // override
+
+@end /* EOAdaptorContext*/
+
+
+@interface EOAdaptorContext(Private)
+- (void)channelDidInit:(id)aChannel;
+- (void)channelWillDealloc:(id)aChannel;
+@end
+
+#import <GDLAccess/EODelegateResponse.h>
+
+@interface NSObject(EOAdaptorContextDelegate)
+
+- (EODelegateResponse)adaptorContextWillBegin:(id)aContext;
+- (void)adaptorContextDidBegin:(id)aContext;
+- (EODelegateResponse)adaptorContextWillCommit:(id)aContext;
+- (void)adaptorContextDidCommit:(id)aContext;
+- (EODelegateResponse)adaptorContextWillRollback:(id)aContext;
+- (void)adaptorContextDidRollback:(id)aContext;
+
+@end /* NSObject(EOAdaptorContextDelegate) */
+
+#endif /* __EOAdaptorContext_h__*/
--- /dev/null
+/*
+ EOAdaptorDataSource.h
+
+ Copyright (C) SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+ Date: 1999-2004
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAdaptorDataSource.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOAdaptorDataSource_h__
+#define __EOAdaptorDataSource_h__
+
+#import <EOControl/EODataSource.h>
+
+@class NSArray, NSDictionary;
+@class EOFetchSpecification, EOAdaptorChannel, EOQualifier;
+
+/*
+ Fetch dictionaries from database tables.
+ The tablename has to be set in [FetchSpecification entityName].
+ Qualifier, sortOrdering, distinct will be evaluated.
+ It handles now tables with more than one primary key.
+ Its possible to set the primary key in the fetchspecification hints
+ (EOPrimaryKeyAttributeNamesHint -> array with strings as columnnames
+ for the PKeys; EOPrimaryKeyAttributesHint -> array with EOAttributes for
+ the PKeys).
+ If no primary key is set, and now primary key could find in the table
+ schema, all keys will be taken as primary keys.
+ If only one primary key exsist, in insert object a new key will be generatet,
+ else all keys has to be set.
+ If fetch hint EOFetchResultTimeZone is set (NSTimeZone), this timezone will
+ be set in date objectes.
+*/
+
+extern NSString *EOPrimaryKeyAttributeNamesHint;
+extern NSString *EOPrimaryKeyAttributesHint;
+extern NSString *EOFetchResultTimeZone;
+
+@interface EOAdaptorDataSource : EODataSource
+{
+@private
+ EOFetchSpecification *fetchSpecification;
+@protected
+ EOAdaptorChannel *adChannel;
+ EOQualifier *__qualifier;
+ NSArray *__attributes;
+ BOOL commitTransaction;
+ NSDictionary *connectionDictionary;
+}
+
+- (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel;
+
+- (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel
+ connectionDictionary:(NSDictionary *)_connDict;
+
+- (id)initWithAdaptorName:(NSString *)_adName
+ connectionDictionary:(NSDictionary *)_dict
+ primaryKeyGenerationDictionary:(NSDictionary *)_pkGen;
+
+
+/*
+ Returns an array with dictionaries, who contains key/values from the
+ entity (use entityName/qualifier/sortOrdering).
+ Also it contains an key named 'globalID'. If EOAdaptorDataSource is
+ initialized with initWithAdaptorChannel the globaID is an EOKeyGlobalID
+ else if it is initialized with initWithAdaptorName the globalID is and
+ EOAdaptorGlobalID.
+*/
+- (NSArray *)fetchObjects;
+
+/*
+ returns an mutable dictionary
+*/
+- (id)createObject;
+
+- (void)insertObject:(id)_obj;
+- (void)deleteObject:(id)_obj;
+- (void)updateObject:(id)_obj;
+
+- (void)setFetchSpecification:(EOFetchSpecification *)_fs;
+- (EOFetchSpecification *)fetchSpecification;
+
+/* for subclasses */
+- (EOAdaptorChannel *)beginTransaction;
+- (void)commitTransaction;
+- (void)rollbackTransaction;
+
+- (void)openChannel;
+- (void)closeChannel;
+@end
+
+#endif /* __EOAdaptorDataSource_h__ */
--- /dev/null
+// $Id: EOAdaptorGlobalID.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOAdaptorGlobalID_H__
+#define __EOAdaptorGlobalID_H__
+
+#include <EOControl/EOGlobalID.h>
+
+@class EOKeyGlobalID, NSDictionary;
+
+@interface EOAdaptorGlobalID : EOGlobalID < NSCopying >
+{
+@protected
+ EOGlobalID *gid;
+ NSDictionary *conDict;
+}
+
+- (id)initWithGlobalID:(EOGlobalID *)_gid
+ connectionDictionary:(NSDictionary *)_conDict;
+
+- (EOGlobalID *)globalID;
+- (NSDictionary *)connectionDictionary;
+
+- (BOOL)isEqual:(id)_obj;
+- (BOOL)isEqualToEOAdaptorGlobalID:(EOAdaptorGlobalID *)_gid;
+
+@end
+
+#endif /* __EOAdaptorGlobalID_H__ */
--- /dev/null
+// $If$
+
+#ifndef __EOAdaptorOperation_H__
+#define __EOAdaptorOperation_H__
+
+#import <Foundation/NSObject.h>
+
+@interface EOAdaptorOperation : NSObject
+@end
+
+#endif /* __EOAdaptorOperation_H__ */
--- /dev/null
+/*
+ EOArrayProxy.h
+
+ Copyright (C) 1999 MDlink online service center GmbH, Helge Hess
+
+ Author: Helge Hess (hh@mdlink.de)
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOArrayProxy.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __eoaccess_EOArrayProxy_H__
+#define __eoaccess_EOArrayProxy_H__
+
+#import <Foundation/NSArray.h>
+
+/*
+ * EOArrayProxy class
+ */
+
+@class NSArray, NSString;
+@class EODatabaseChannel, EOSQLQualifier, EOEntity;
+
+@interface EOArrayProxy : NSArray
+{
+@private
+ EODatabaseChannel *channel;
+ EOSQLQualifier *qualifier;
+ NSArray *fetchOrder;
+ NSArray *content;
+}
+
++ (id)arrayProxyWithQualifier:(EOSQLQualifier *)_qualifier
+ fetchOrder:(NSArray *)_fetchOrder
+ channel:(EODatabaseChannel *)_channel;
+
+// accessors
+
+- (BOOL)isFetched;
+- (EODatabaseChannel *)databaseChannel;
+- (EOEntity *)entity;
+- (NSArray *)fetchOrder;
+- (EOSQLQualifier *)qualifier;
+
+// operations
+
+- (BOOL)fetch;
+
+@end
+
+#endif /* __eoaccess_EOArrayProxy_H__ */
--- /dev/null
+/*
+ EOAttribute.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOAttribute_h__
+#define __EOAttribute_h__
+
+#import <Foundation/NSString.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSDate.h>
+
+@class NSString, NSTimeZone, NSDate, NSException;
+@class NSMutableArray;
+@class EOEntity;
+
+@interface EOAttribute : NSObject
+{
+ NSString *name;
+ NSString *calendarFormat;
+ NSTimeZone *clientTimeZone;
+ NSTimeZone *serverTimeZone;
+ NSString *columnName;
+ NSString *definition;
+ NSString *externalType;
+ NSString *valueClassName;
+ NSString *valueType;
+ NSString *insertFormat;
+ NSString *selectFormat;
+ NSString *updateFormat;
+ NSDictionary *userDictionary;
+
+ /* Garbage collectable objects */
+ EOEntity *entity; /* non-retained */
+ NSMutableArray *definitionArray; // These variables are meaningful only
+ EOAttribute *realAttribute; // if the attribute is flattened
+ unsigned width;
+
+ struct {
+ BOOL isReadOnly:1;
+ BOOL isDerived:1;
+ BOOL isFlattened:1;
+ BOOL allowsNull:1;
+ } flags;
+}
+
+/* Initializing new instances */
+- (id)initWithName:(NSString*)name;
+
+/* Accessing the entity */
+- (void)setEntity:(EOEntity*)entity;
+- (EOEntity*)entity;
+- (void)resetEntity;
+- (BOOL)hasEntity;
+
+/* Accessing the name */
+- (BOOL)setName:(NSString*)name;
+- (NSString*)name;
++ (BOOL)isValidName:(NSString*)name;
+
+/* Accessing date information */
++ (NSString*)defaultCalendarFormat;
+- (void)setCalendarFormat:(NSString*)format;
+- (NSString*)calendarFormat;
+- (void)setClientTimeZone:(NSTimeZone*)tz;
+- (NSTimeZone*)clientTimeZone;
+- (void)setServerTimeZone:(NSTimeZone*)tz;
+- (NSTimeZone*)serverTimeZone;
+
+/* Accessing external definitions */
+- (void)setColumnName:(NSString*)columnName;
+- (NSString*)columnName;
+- (void)setDefinition:(NSString*)definition;
+- (NSString*)definition;
+- (NSMutableArray*)definitionArray;
+- (void)setExternalType:(NSString*)type;
+- (NSString*)externalType;
+
+/* Accessing value type information */
+- (void)setValueClassName:(NSString*)name;
+- (NSString*)valueClassName;
+- (void)setValueType:(NSString*)type;
+- (NSString*)valueType;
+
+/* Checking type information */
+- (BOOL)referencesProperty:property;
+- (BOOL)isDerived;
+- (BOOL)isFlattened;
+- (BOOL)setReadOnly:(BOOL)flag;
+- (BOOL)isReadOnly;
+
+/* Accessing SQL statement formats */
+- (void)setInsertFormat:(NSString*)string;
+- (NSString*)insertFormat;
+- (void)setSelectFormat:(NSString*)string;
+- (NSString*)selectFormat;
+- (void)setUpdateFormat:(NSString*)string;
+- (NSString*)updateFormat;
+
+/* Accessing the user dictionary */
+- (void)setUserDictionary:(NSDictionary*)dictionary;
+- (NSDictionary*)userDictionary;
+
+/* Obsolete. This method always return NO, because you should always release
+ a property. */
+- (BOOL)referencesProperty:property;
+
+@end
+
+
+@interface EOAttribute (EOAttributePrivate)
+
++ (EOAttribute*)attributeFromPropertyList:(id)propertyList;
+- (void)replaceStringsWithObjects;
+- (id)propertyList;
+
+@end /* EOAttribute (EOAttributePrivate) */
+
+@interface EOAttribute(ValuesConversion)
+
+- (id)convertValue:(id)aValue
+ toClass:(Class)aClass
+ forType:(NSString *)aValueType;
+- (id)convertValueToModel:(id)aValue;
+
+@end /* EOAttribute (ValuesConversion) */
+
+@interface NSString (EOAttributeTypeCheck)
+
+- (BOOL)isNameOfARelationshipPath;
+
+@end
+
+@class NSMutableDictionary;
+
+@interface EOAttribute(PropertyListCoding)
+
+- (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist;
+
+@end
+
+@interface EOAttribute(EOF2Additions)
+
+- (void)beautifyName;
+
+/* constraints */
+
+- (void)setAllowsNull:(BOOL)_flag;
+- (BOOL)allowsNull;
+- (void)setWidth:(unsigned)_width;
+- (unsigned)width;
+
+- (NSException *)validateValue:(id *)_value;
+
+- (NSString *)readFormat;
+- (NSString *)writeFormat;
+
+@end
+
+#endif /* __EOAttribute_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOAttributeOrdering.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOAttributeOrdering_h__
+#define __EOAttributeOrdering_h__
+
+#import <Foundation/NSObject.h>
+
+@class EOAttribute;
+
+typedef enum {
+ EOAnyOrder,
+ EOAscendingOrder,
+ EODescendingOrder
+} EOOrdering;
+
+@interface EOAttributeOrdering : NSObject
+{
+ EOAttribute* attribute;
+ EOOrdering ordering;
+}
+
+/* Creating an attribute ordering */
++ attributeOrderingWithAttribute:(EOAttribute*)attribute
+ ordering:(EOOrdering)ordering;
+- initWithAttribute:(EOAttribute*)attribute
+ ordering:(EOOrdering)ordering;
+
+/* Getting values */
+- (EOAttribute*)attribute;
+- (EOOrdering)ordering;
+
+@end
+
+#endif /* __EOAttributeOrdering_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOCustomValues.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOCustomValues_h__
+#define __EOCustomValues_h__
+
+#import <Foundation/NSString.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSValue.h>
+
+/*
+ * Informal protocols to initialize value-instances (used as objects
+ * in the dictionaries for the enterprise objects) and to convert
+ * those values to string or data.
+ * NOT implemented in NSObject
+ */
+
+@interface NSObject(EOCustomValues)
+- (id)initWithString:(NSString*)string type:(NSString*)type;
+- (NSString*)stringForType:(NSString*)type;
+@end
+
+@interface NSObject(EODatabaseCustomValues)
+- (id)initWithData:(NSData*)data type:(NSString*)type;
+- (NSData*)dataForType:(NSString*)type;
+@end
+
+/*
+ * These categories are added to NSString, NSData and NSNumber classes.
+ */
+
+@interface NSString(EOCustomValues)
++ stringWithString:(NSString*)string type:(NSString*)type;
+- (id)initWithString:(NSString*)string type:(NSString*)type;
+- (NSString*)stringForType:(NSString*)type;
+- (id)initWithData:(NSData*)data type:(NSString*)type;
+- (NSData*)dataForType:(NSString*)type;
+@end
+
+@interface NSData(EOCustomValues)
+- initWithString:(NSString*)string type:(NSString*)type;
+- (NSString*)stringForType:(NSString*)type;
+- (id)initWithData:(NSData*)data type:(NSString*)type;
+- (NSData*)dataForType:(NSString*)type;
+@end
+
+@interface NSNumber(EOCustomValues)
++ (id)numberWithString:(NSString*)string type:(NSString*)type;
+- (id)initWithString:(NSString*)string type:(NSString*)type;
+- (NSString*)stringForType:(NSString*)type;
+@end
+
+#endif /* __EOCustomValues_h__ */
+
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EODatabase.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __eoaccess_EODatabase_h__
+#define __eoaccess_EODatabase_h__
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSDate.h>
+
+@class NSArray;
+@class NSMutableArray;
+@class NSDictionary;
+@class NSMutableDictionary;
+@class NSString;
+@class NSMutableString;
+
+@class EOAdaptor;
+@class EOModel;
+@class EOEntity;
+
+@class EOObjectUniquer;
+@class EODatabase, EODatabaseContext, EODatabaseChannel;
+
+@protocol EOObjectRegistry
+
+- (void)forgetObject:(id)anObj;
+- (id)objectForPrimaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity;
+
+/* retrieving snapshots and primary keys */
+
+- (NSDictionary *)snapshotForObject:(id)anObj;
+- (NSDictionary *)primaryKeyForObject:(id)anObj;
+- (void)primaryKey:(NSDictionary **)aKey
+ andSnapshot:(NSDictionary **)aSnapshot
+ forObject:(id)anObj;
+
+/* recording objects */
+
+- (void)recordObject:(id)anObj
+ primaryKey:(NSDictionary *)aKey
+ snapshot:(NSDictionary *)aSnapshot;
+
+- (void)recordObject:(id)anObj
+ primaryKey:(NSDictionary *)aKey
+ entity:(EOEntity *)anEntity
+ snapshot:(NSDictionary *)aSnapshot;
+
+@end
+
+@interface EODatabase : NSObject < EOObjectRegistry >
+{
+ @private
+ EOAdaptor *adaptor;
+ EOObjectUniquer *objectsDictionary;
+ NSMutableArray *contexts;
+
+ struct {
+ BOOL isUniquingObjects:1;
+ BOOL isKeepingSnapshots:1;
+ BOOL isLoggingWarnings:1;
+ } flags;
+}
+
+// Initializing new instances
+- (id)initWithAdaptor:(EOAdaptor *)anAdaptor;
+- (id)initWithModel:(EOModel *)aModel;
+
+// Getting the adaptor
+- (EOAdaptor*)adaptor;
+
+// Getting the database contexts
+- (id)createContext;
+- (NSArray*)contexts;
+
+// Checking connection status
+- (BOOL)hasOpenChannels;
+
+// Uniquing/snapshotting
+- (void)setUniquesObjects:(BOOL)yn;
+- (BOOL)uniquesObjects;
+- (void)setKeepsSnapshots:(BOOL)yn;
+- (BOOL)keepsSnapshots;
+
+// Handle Objects
++ (void)forgetObject:(id)anObj;
+- (void)forgetAllObjects;
+- (void)forgetAllSnapshots;
+
+- (BOOL)isObject:(id)anObj updatedOutsideContext:(EODatabaseContext *)aContext;
+
+// Error messages
+- (BOOL)logsErrorMessages;
+- (void)setLogsErrorMessages:(BOOL)yn;
+- (void)reportError:(NSString*)error;
+- (void)reportErrorFormat:(NSString*)format, ...;
+- (void)reportErrorFormat:(NSString*)format arguments:(va_list)arguments;
+
+@end /* EODatabase */
+
+/*
+ * Methods used by database classes internally
+ */
+
+@interface EODatabase(Private)
+- (void)contextDidInit:(id)aContext;
+- (void)contextWillDealloc:(id)aContext;
+- (EOObjectUniquer*)objectUniquer;
+@end
+
+@class EOGlobalID;
+
+extern NSTimeInterval NSDistantPastTimeInterval;
+
+@interface EODatabase(EOF2Additions)
+
+/* models */
+
+- (NSArray *)models;
+- (void)addModel:(EOModel *)_model;
+- (BOOL)addModelIfCompatible:(EOModel *)_model;
+
+/* entities */
+
+- (EOEntity *)entityForObject:(id)_object;
+- (EOEntity *)entityNamed:(NSString *)_name;
+
+/* snapshots */
+
+- (void)recordSnapshot:(NSDictionary *)_snapshot forGlobalID:(EOGlobalID *)_gid;
+- (void)recordSnapshots:(NSDictionary *)_snapshots;
+
+- (void)recordSnapshot:(NSArray *)_gids
+ forSourceGlobalID:(EOGlobalID *)_gid
+ relationshipName:(NSString *)_name;
+- (void)recordToManySnapshots:(NSDictionary *)_snapshots;
+
+- (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid
+ after:(NSTimeInterval)_duration;
+- (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid;
+
+- (void)forgetSnapshotsForGlobalIDs:(NSArray *)_gids;
+- (void)forgetSnapshotsForGlobalID:(EOGlobalID *)_gid;
+
+@end
+
+#endif /* __eoaccess_EODatabase_h__ */
--- /dev/null
+/*
+ EODatabaseChannel.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EODatabaseChannel_h__
+#define __EODatabaseChannel_h__
+
+#import <Foundation/NSObject.h>
+
+@class NSArray, NSMutableArray, NSDictionary, NSMutableDictionary;
+@class NSString, NSMutableString, NSNotificationCenter;
+@class EOAdaptor, EOAdaptorContext, EOAdaptorChannel;
+@class EOEntity, EOSQLQualifier, EORelationship;
+@class EOObjectUniquer, EODatabase, EODatabaseContext;
+@class EOGlobalID;
+
+extern NSString *EODatabaseChannelWillOpenNotificationName;
+extern NSString *EODatabaseChannelDidOpenNotificationName;
+extern NSString *EODatabaseChannelCouldNotOpenNotificationName;
+extern NSString *EODatabaseChannelWillCloseNotificationName;
+extern NSString *EODatabaseChannelDidCloseNotificationName;
+extern NSString *EODatabaseChannelWillInsertObjectName;
+extern NSString *EODatabaseChannelDidInsertObjectName;
+extern NSString *EODatabaseChannelWillUpdateObjectName;
+extern NSString *EODatabaseChannelDidUpdateObjectName;
+extern NSString *EODatabaseChannelWillDeleteObjectName;
+extern NSString *EODatabaseChannelDidDeleteObjectName;
+extern NSString *EODatabaseChannelWillLockObjectName;
+extern NSString *EODatabaseChannelDidLockObjectName;
+
+@interface EODatabaseChannel : NSObject
+{
+@private
+ NSNotificationCenter *notificationCenter;
+ EOAdaptorChannel *adaptorChannel;
+ EODatabaseContext *databaseContext;
+ id delegate;
+ EOEntity *currentEntity;
+ Class currentClass;
+ NSArray *currentAttributes;
+ NSArray *currentRelations;
+ BOOL currentReady;
+ id currentEditingContext;
+
+ /* statistics */
+ unsigned int successfulOpenCount;
+ unsigned int failedOpenCount;
+ unsigned int closeCount;
+ unsigned int insertCount;
+ unsigned int updateCount;
+ unsigned int deleteCount;
+ unsigned int lockCount;
+}
+
+// Initializing a new instance
+- (id)initWithDatabaseContext:(EODatabaseContext*)aDatabaseContext;
+
+// Getting the adaptor channel
+- (EOAdaptorChannel*)adaptorChannel;
+
+// Getting the database context
+- (EODatabaseContext*)databaseContext;
+
+// Setting the delegate
+- (void)setDelegate:(id)aDelegate;
+- (id)delegate;
+
+// Opening and closing a channel
+- (BOOL)isOpen;
+- (BOOL)openChannel;
+- (void)closeChannel;
+
+// Modifying objects
+- (BOOL)insertObject:(id)anObj;
+- (BOOL)updateObject:(id)anObj;
+- (BOOL)deleteObject:(id)anObj;
+- (BOOL)lockObject:(id)anObj;
+- (BOOL)refetchObject:(id)anObj;
+- (id)allocateObjectForRow:(NSDictionary*)row
+ entity:(EOEntity*)anEntity
+ zone:(NSZone*)zone;
+- (id)initializedObjectForRow:(NSDictionary*)row
+ entity:(EOEntity*)anEntity
+ zone:(NSZone*)zone;
+
+// Fetching objects
+- (BOOL)selectObjectsDescribedByQualifier:(EOSQLQualifier*)qualifier
+ fetchOrder:(NSArray*)fetchOrder;
+- (id)fetchWithZone:(NSZone*)zone;
+- (BOOL)isFetchInProgress;
+- (void)cancelFetch;
+- (void)setCurrentEntity:(EOEntity*)anEntity;
+
+@end /* EODatabaseChannel */
+
+/* statistics */
+
+@interface EODatabaseChannel(Statistics)
+- (unsigned int)successfulOpenCount;
+- (unsigned int)failedOpenCount;
+- (unsigned int)closeCount;
+- (unsigned int)insertCount;
+- (unsigned int)updateCount;
+- (unsigned int)deleteCount;
+- (unsigned int)lockCount;
+@end
+
+/*
+ * Delegate methods
+ */
+
+@interface NSObject(EODatabaseChannelDelegateProtocol)
+
+- (id)databaseChannel:aChannel
+ willInsertObject:anObj;
+- (void)databaseChannel:aChannel
+ didInsertObject:anObj;
+- (id)databaseChannel:aChannel
+ willDeleteObject:anObj;
+- (void)databaseChannel:aChannel
+ didDeleteObject:anObj;
+- (id)databaseChannel:aChannel
+ willUpdateObject:anObj;
+- (void)databaseChannel:aChannel
+ didUpdateObject:anObj;
+- (NSDictionary*)databaseChannel:aChannel
+ willRefetchObject:anObj;
+- (NSDictionary*)databaseChannel:aChannel
+ didRefetchObject:anObj;
+- (NSDictionary*)databaseChannel:aChannel
+ willRefetchObject:anObj
+ fromSnapshot:(NSDictionary*)snapshot;
+- (NSDictionary*)databaseChannel:aChannel
+ willRefetchConflictingObject:anObj
+ withSnapshot:(NSMutableDictionary*)snapshot;
+- (BOOL)databaseChannel:aChannel
+ willSelectObjectsDescribedByQualifier:(EOSQLQualifier*)qualifier
+ fetchOrder:(NSArray*)fetchOrder;
+- (void)databaseChannel:aChannel
+ didSelectObjectsDescribedByQualifier:(EOSQLQualifier*)qualifier
+ fetchOrder:(NSArray*)fetchOrder;
+- (void)databaseChannel:aChannel
+ willFetchObjectOfClass:(Class)class
+ withZone:(NSZone*)zone;
+- (void)databaseChannel:aChannel
+ didFetchObject:anObj;
+- databaseChannel:aChannel
+ willLockObject:anObj;
+- (void)databaseChannel:aChannel
+ didLockObject:anObj;
+- (Class)databaseChannel:aChannel
+ failedToLookupClassNamed:(const char*)name;
+- (EORelationship*)databaseChannel:aChannel
+ relationshipForRow:(NSDictionary*)row
+ relationship:(EORelationship*)relationship;
+
+@end
+
+@interface NSObject(EODatabaseChannelEONotifications)
+
+- (BOOL)prepareForDeleteInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+- (void)wasDeletedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+
+- (BOOL)prepareForInsertInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+- (void)wasInsertedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+
+- (BOOL)prepareForUpdateInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+- (void)wasUpdatedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+
+- (BOOL)prepareForLockInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+- (void)wasLockedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx;
+
+@end
+
+/*
+ * Object Awaking (EODatabaseChannelNotification protocol)
+ */
+
+@interface NSObject(EODatabaseChannelNotification)
+- (void)awakeForDatabaseChannel:(EODatabaseChannel*)channel;
+@end
+
+#endif /* __EODatabaseChannel_h__ */
--- /dev/null
+/*
+ EODatabaseContext.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EODatabaseContext_h__
+#define __EODatabaseContext_h__
+
+#import <Foundation/NSObject.h>
+#import <GDLAccess/EODatabase.h>
+
+@class NSArray, NSMutableArray, NSDictionary, NSMutableDictionary;
+@class NSString, NSMutableString;
+@class EOAdaptorContext;
+@class EOEntity;
+@class EOObjectUniquer, EODatabase, EODatabaseContext, EODatabaseChannel;
+
+typedef enum {
+ EOUpdateWithOptimisticLocking,
+ EOUpdateWithPessimisticLocking,
+ EOUpdateWithNoLocking,
+ EONoUpdate,
+} EOUpdateStrategy;
+
+struct _EOTransactionScope;
+
+extern NSString *EODatabaseContextWillBeginTransactionName;
+extern NSString *EODatabaseContextDidBeginTransactionName;
+extern NSString *EODatabaseContextWillRollbackTransactionName;
+extern NSString *EODatabaseContextDidRollbackTransactionName;
+extern NSString *EODatabaseContextWillCommitTransactionName;
+extern NSString *EODatabaseContextDidCommitTransactionName;
+
+struct EODatabaseContextModificationQueue;
+
+@interface EODatabaseContext : NSObject < EOObjectRegistry >
+//EOCooperatingObjectStore < EOObjectRegistry >
+{
+ EOAdaptorContext *adaptorContext;
+ EODatabase *database;
+ NSMutableArray *channels;
+ EOUpdateStrategy updateStrategy;
+ id coordinator;
+ id delegate; /* non-retained */
+
+ struct _EOTransactionScope *transactionStackTop;
+ int transactionNestingLevel;
+
+ // These fields should be in a bitfield but are ivars for debug purposes
+ BOOL isKeepingSnapshots;
+ BOOL isUniquingObjects;
+
+ /* modified objects */
+ struct EODatabaseContextModificationQueue *ops;
+
+ /* statistics */
+ unsigned int txBeginCount;
+ unsigned int txCommitCount;
+ unsigned int txRollbackCount;
+}
+
+// Initializing instances
+- (id)initWithDatabase:(EODatabase *)aDatabase;
+
+/* accessors */
+
+- (void)setDelegate:(id)_delegate;
+- (id)delegate;
+- (EODatabase *)database;
+
+// Getting the adaptor context
+- (EOAdaptorContext*)adaptorContext;
+
+// Finding channels
+- (BOOL)hasBusyChannels;
+- (BOOL)hasOpenChannels;
+- (NSArray *)channels;
+- (id)createChannel;
+
+// Controlling transactions
+- (BOOL)beginTransaction;
+- (BOOL)commitTransaction;
+- (BOOL)rollbackTransaction;
+
+// Notifying of other transactions
+- (void)transactionDidBegin;
+- (void)transactionDidCommit;
+- (void)transactionDidRollback;
+
+// Nesting transactions
+- (BOOL)canNestTransactions;
+- (unsigned)transactionNestingLevel;
+
+// Setting the update strategy
+- (void)setUpdateStrategy:(EOUpdateStrategy)aStrategy;
+- (EOUpdateStrategy)updateStrategy;
+- (BOOL)keepsSnapshots;
+
+// Handle Objects
+
+- (void)recordLockedObject:(id)anObj;
+- (BOOL)isObjectLocked:(id)anObj;
+- (void)recordUpdatedObject:(id)anObj;
+- (BOOL)isObjectUpdated:(id)anObj;
+
+@end /* EODatabaseContext */
+
+@interface EODatabaseContext(Statistics)
+
+- (unsigned int)transactionBeginCount;
+- (unsigned int)transactionCommitCount;
+- (unsigned int)transactionRollbackCount;
+
+@end
+
+/*
+ * Methods used by database classess internally
+ */
+
+@interface EODatabaseContext(Private)
+- (void)channelDidInit:(id)aChannel;
+- (void)channelWillDealloc:(id)aChannel;
+- (void)privateBeginTransaction;
+- (void)privateCommitTransaction;
+- (void)privateRollbackTransaction;
+@end
+
+@class EOModel;
+
+@interface EODatabaseContext(NewInEOF2)
+
++ (void)setContextClassToRegister:(Class)_cclass;
++ (Class)contextClassToRegister;
+
+#if 0
++ (EODatabaseContext *)registeredDatabaseContextForModel:(EOModel *)_model
+ editingContext:(id)_ec;
+
+- (id)coordinator;
+#endif
+
+/* managing channels */
+
+- (EODatabaseChannel *)availableChannel;
+- (NSArray *)registeredChannels;
+- (void)registerChannel:(EODatabaseChannel *)_channel;
+- (void)unregisterChannel:(EODatabaseChannel *)_channel;
+
+@end
+
+@class EOFetchSpecification;
+
+@interface NSObject(EOF2DelegateMethods)
+
+- (BOOL)databaseContext:(EODatabaseContext *)_ctx
+ shouldSelectObjectsWithFetchSpecification:(EOFetchSpecification *)_fspec
+ databaseChannel:(EODatabaseChannel *)_channel;
+
+- (void)databaseContext:(EODatabaseContext *)_ctx
+ didSelectObjectsWithFetchSpecification:(EOFetchSpecification *)_fspec
+ databaseChannel:(EODatabaseChannel *)_channel;
+
+- (BOOL)databaseContext:(EODatabaseContext *)_ctx
+ shouldUsePessimisticLockWithFetchSpecification:(EOFetchSpecification *)_fspec
+ databaseChannel:(EODatabaseChannel *)_channel;
+
+@end
+
+#endif /* __EODatabaseContext_h__ */
--- /dev/null
+/*
+ EODatabaseFault.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __eoaccess_EODatabaseFault_h__
+#define __eoaccess_EODatabaseFault_h__
+
+#import <GDLAccess/EOFault.h>
+
+@class EOSQLQualifier, EOEntity, EODatabaseChannel;
+@class NSArray, NSDictionary, NSString;
+
+/*
+ * EODatabaseFault class
+ */
+
+@interface EODatabaseFault : EOFault
+
+// Creating a fault
+
++ (id)objectFaultWithPrimaryKey:(NSDictionary*)key
+ entity:(EOEntity*)entity
+ databaseChannel:(EODatabaseChannel*)channel
+ zone:(NSZone*)zone;
+
++ (NSArray *)arrayFaultWithQualifier:(EOSQLQualifier*)qualifier
+ fetchOrder:(NSArray*)fetchOrder
+ databaseChannel:(EODatabaseChannel*)channel
+ zone:(NSZone*)zone;
++ (NSArray *)gcArrayFaultWithQualifier:(EOSQLQualifier*)qualifier
+ fetchOrder:(NSArray*)fetchOrder
+ databaseChannel:(EODatabaseChannel*)channel
+ zone:(NSZone*)zone;
+
++ (NSDictionary*)primaryKeyForFault:fault;
++ (EOEntity*)entityForFault:fault;
++ (EOSQLQualifier*)qualifierForFault:fault;
++ (NSArray*)fetchOrderForFault:fault;
++ (EODatabaseChannel*)databaseChannelForFault:fault;
+
+@end /* EODatabaseFault */
+
+/*
+ * Informal protocol that informs an instance that a to-one
+ * relationship could not be resoved to get data for self.
+ * Its implementation in NSObject raises NSObjectNotAvailableException.
+ */
+
+@interface NSObject(EOUnableToFaultToOne)
+- (void)unableToFaultWithPrimaryKey:(NSDictionary*)key
+ entity:(EOEntity*)entity
+ databaseChannel:(EODatabaseChannel*)channel;
+@end
+
+#endif /* __eoaccess_EODatabaseFault_h__ */
--- /dev/null
+/*
+ EODatabaseFaultResolver.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ Author: Helge Hess <helge.hess@mdlink.de>
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EODatabaseFaultResolver_h__
+#define __EODatabaseFaultResolver_h__
+
+#import <GDLAccess/EOFault.h>
+
+@class EODatabaseChannel;
+@class EOSQLQualifier;
+@class EOEntity;
+
+@interface EODatabaseFaultResolver : EOFaultHandler
+{
+@public
+ EODatabaseChannel *channel;
+}
+
+- (id)initWithDatabaseChannel:(EODatabaseChannel*)aChannel
+ zone:(NSZone*)zone
+ targetClass:(Class)targetClass;
+
+- (Class)targetClass;
+- (NSDictionary *)primaryKey;
+- (EOEntity *)entity;
+- (EOSQLQualifier *)qualifier;
+- (NSArray *)fetchOrder;
+- (EODatabaseChannel *)databaseChannel;
+
+@end /* EODatabaseFaultResolver */
+
+@interface EOArrayFault : EODatabaseFaultResolver
+{
+ EOSQLQualifier *qualifier;
+ NSArray *fetchOrder;
+}
+
+- (id)initWithQualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ databaseChannel:(EODatabaseChannel *)channel
+ zone:(NSZone *)zone
+ targetClass:(Class)targetClass;
+
+- (EOEntity *)entity;
+- (EOSQLQualifier *)qualifier;
+- (NSArray *)fetchOrder;
+
+@end
+
+@interface EOObjectFault : EODatabaseFaultResolver
+{
+ EOEntity *entity;
+ NSDictionary *primaryKey;
+}
+
+- (id)initWithPrimaryKey:(NSDictionary *)key
+ entity:(EOEntity *)entity
+ databaseChannel:(EODatabaseChannel *)channel
+ zone:(NSZone *)zone
+ targetClass:(Class)targetClass ;
+
+- (NSDictionary*)primaryKey;
+- (EOEntity*)entity;
+
+@end
+
+#endif /* __EODatabaseFaultResolver_h__ */
--- /dev/null
+// $Id: EODelegateResponse.h 1 2004-08-20 10:38:46Z znek $
+
+typedef enum {
+ EODelegateRejects,
+ EODelegateApproves,
+ EODelegateOverrides
+} EODelegateResponse;
--- /dev/null
+// $Id: EOEntity+Factory.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __GDLAccess_EOEntity_Factory_H__
+#define __GDLAccess_EOEntity_Factory_H__
+
+#import <GDLAccess/EOEntity.h>
+
+@class NSDictionary;
+@class EOAttribute;
+
+@interface EOEntity(AttributeNames)
+
+- (NSArray *)attributeNames;
+
+@end
+
+@interface EOEntity(PrimaryKeys)
+
+- (BOOL)isPrimaryKeyAttribute:(EOAttribute *)_attribute;
+- (unsigned)primaryKeyCount;
+
+@end
+
+@interface EOEntity(ObjectFactory)
+
+- (id)produceNewObjectWithPrimaryKey:(NSDictionary *)_key;
+- (void)setAttributesOfObjectToEONull:(id)_object;
+
+@end
+
+#endif /* __GDLAccess_EOEntity_Factory_H__ */
--- /dev/null
+/*
+ EOEntity.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOEntity_h__
+#define __EOEntity_h__
+
+#import <Foundation/NSString.h>
+
+@class EOModel, EOAttribute, EORelationship;
+@class EOSQLQualifier, EOExpressionArray;
+@class NSMutableDictionary;
+
+@interface EOEntity : NSObject
+{
+ NSString *name;
+ NSString *className;
+ NSString *externalName;
+ NSString *externalQuery;
+ NSDictionary *userDictionary;
+ NSArray *primaryKeyAttributeNames; /* sorted array of names */
+ NSArray *attributesNamesUsedForInsert;
+ NSArray *classPropertyNames;
+
+ /* Garbage collectable objects */
+ EOModel *model; /* non-retained */
+ EOSQLQualifier *qualifier;
+ NSArray *attributes;
+ NSMutableDictionary *attributesByName;
+ NSArray *relationships;
+ NSMutableDictionary *relationshipsByName; // name/EORelationship
+ NSArray *primaryKeyAttributes;
+ NSArray *classProperties; // EOAttribute/EORelationship
+ NSArray *attributesUsedForLocking;
+
+ /* Cached properties */
+ NSArray *attributesUsedForInsert; // cache from classProperties
+ NSArray *attributesUsedForFetch; // cache from classProperties
+ NSArray *relationsUsedForFetch; // cache from classProperties
+
+ struct {
+ BOOL isReadOnly:1;
+ BOOL createsMutableObjects:1;
+ BOOL isPropertiesCacheValid:1;
+ } flags;
+}
+
+/* Initializing instances */
+- (id)initWithName:(NSString *)name;
+
+/* Accessing the name */
+- (NSString *)name;
+- (BOOL)setName:(NSString *)name;
++ (BOOL)isValidName:(NSString *)name;
+
+/* Accessing the model */
+- (void)setModel:(EOModel *)model;
+- (EOModel *)model;
+- (void)resetModel;
+- (BOOL)hasModel;
+
+/* Getting the qualifier */
+- (EOSQLQualifier *)qualifier;
+
+/* Accessing attributes */
+- (BOOL)addAttribute:(EOAttribute *)attribute;
+- (void)removeAttributeNamed:(NSString *)name;
+- (EOAttribute *)attributeNamed:(NSString *)attributeName;
+- (NSArray *)attributes;
+
+/* Accessing relationships */
+- (BOOL)addRelationship:(EORelationship *)relationship;
+- (void)removeRelationshipNamed:(NSString *)name;
+- (EORelationship *)relationshipNamed:(NSString *)relationshipName;
+- (NSArray *)relationships;
+
+/* Accessing primary key attributes */
+- (BOOL)setPrimaryKeyAttributes:(NSArray *)keys;
+- (NSArray *)primaryKeyAttributes;
+- (NSArray *)primaryKeyAttributeNames;
+- (BOOL)isValidPrimaryKeyAttribute:(EOAttribute *)anAttribute;
+
+/* Getting primary keys and snapshot for row */
+- (NSDictionary *)primaryKeyForRow:(NSDictionary *)row;
+- (NSDictionary *)snapshotForRow:(NSDictionary *)aRow;
+
+/* Getting attributes used for fetch/insert/update operations */
+- (NSArray *)attributesUsedForInsert;
+- (NSArray *)attributesUsedForFetch;
+- (NSArray *)relationsUsedForFetch;
+- (NSArray *)attributesNamesUsedForInsert;
+
+/* Accessing class properties */
+- (BOOL)setClassProperties:(NSArray *)properties;
+- (NSArray *)classProperties;
+- (NSArray *)classPropertyNames;
+- (BOOL)isValidClassProperty:(id)aProp;
+- (id)propertyNamed:(NSString *)name;
+- (NSArray *)relationshipsNamed:(NSString *)_relationshipPath;
+
+/* Accessing locking attributes */
+- (BOOL)setAttributesUsedForLocking:(NSArray *)attributes;
+- (NSArray *)attributesUsedForLocking;
+- (BOOL)isValidAttributeUsedForLocking:(EOAttribute *)anAttribute;
+
+/* Accessing the enterprise object class */
+- (void)setClassName:(NSString *)name;
+- (NSString *)className;
+
+/* Accessing external information */
+- (void)setExternalName:(NSString *)name;
+- (NSString *)externalName;
+
+/* Accessing the external query */
+- (void)setExternalQuery:(NSString *)query;
+- (NSString *)externalQuery;
+
+/* Accessing read-only status */
+- (void)setReadOnly:(BOOL)flag;
+- (BOOL)isReadOnly;
+
+/* Accessing the user dictionary */
+- (void)setUserDictionary:(NSDictionary *)dictionary;
+- (NSDictionary *)userDictionary;
+
+- (BOOL)referencesProperty:property;
+
+@end
+
+
+@interface EOEntity (EOEntityPrivate)
+
++ (EOEntity *)entityFromPropertyList:(id)propertyList model:(EOModel *)model;
+- (void)replaceStringsWithObjects;
+
+- (id)propertyList;
+- (void)setCreateMutableObjects:(BOOL)flag;
+- (BOOL)createsMutableObjects;
+
+- (void)validatePropertiesCache;
+- (void)invalidatePropertiesCache;
+
+@end
+
+@interface EOEntity(ValuesConversion)
+
+- (NSDictionary *)convertValuesToModel:(NSDictionary *)aRow;
+
+@end /* EOAttribute (ValuesConversion) */
+
+@class EOGlobalID, EOFetchSpecification;
+
+@interface EOEntity(EOF2Additions)
+
+- (BOOL)isAbstractEntity;
+
+/* ids */
+
+- (EOGlobalID *)globalIDForRow:(NSDictionary *)_row;
+- (BOOL)isPrimaryKeyValidInObject:(id)_object;
+
+/* refs to other models */
+
+- (NSArray *)externalModelsReferenced;
+
+/* fetch specs */
+
+- (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name;
+- (NSArray *)fetchSpecificationNames;
+
+/* names */
+
+- (void)beautifyName;
+
+@end
+
+@class NSMutableDictionary;
+
+@interface EOEntity(PropertyListCoding)
+
+- (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist;
+
+@end
+
+#import <EOControl/EOClassDescription.h>
+
+@interface EOEntityClassDescription : EOClassDescription
+{
+ EOEntity *entity;
+}
+
+- (id)initWithEntity:(EOEntity *)_entity;
+- (EOEntity *)entity;
+
+@end
+
+#endif /* __EOEntity_h__ */
--- /dev/null
+/*
+ EOExpressionArray.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: September 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOExpressionArray_h__
+#define __EOExpressionArray_h__
+
+#import <Foundation/NSString.h>
+
+@class EOAttribute, EOEntity, EOExpressionArray;
+
+@protocol EOExpressionContext <NSObject>
+
+- (NSString *)expressionValueForAttribute:(EOAttribute *)anAttribute;
+- (NSString *)expressionValueForAttributePath:(NSArray *)path;
+
+@end
+
+
+@interface EOExpressionArray : NSObject < NSMutableCopying >
+{
+@protected
+ NSMutableArray *array;
+ NSString *prefix;
+ NSString *infix;
+ NSString *suffix;
+}
+
+/* Initializing instances */
+- (id)initWithPrefix:(NSString*)prefix
+ infix:(NSString*)infix
+ suffix:(NSString*)suffix;
+
+/* Accessing the components */
+- (void)setPrefix:(NSString*)prefix;
+- (NSString*)prefix;
+- (void)setInfix:(NSString*)infix;
+- (NSString*)infix;
+- (void)setSuffix:(NSString*)suffix;
+- (NSString*)suffix;
+
+/* Checking contents */
+- (BOOL)referencesObject:(id)anObject;
+
+- (NSString*)expressionValueForContext:(id<EOExpressionContext>)ctx;
+
++ (EOExpressionArray*)parseExpression:(NSString*)expression
+ entity:(EOEntity*)entity
+ replacePropertyReferences:(BOOL)flag;
+
++ (EOExpressionArray*)parseExpression:(NSString*)expression
+ entity:(EOEntity*)entity
+ replacePropertyReferences:(BOOL)flag
+ relationshipPaths:(NSMutableArray *)relationshipPaths;
+
+// array compatibility
+
+- (void)addObjectsFromExpressionArray:(EOExpressionArray *)_array;
+
+- (void)insertObject:(id)_obj atIndex:(unsigned int)_idx;
+- (void)addObjectsFromArray:(NSArray *)_array;
+- (void)addObject:(id)_object;
+- (unsigned int)indexOfObject:(id)_object;
+- (id)objectAtIndex:(unsigned int)_idx;
+- (id)lastObject;
+- (unsigned int)count;
+- (NSEnumerator *)objectEnumerator;
+- (NSEnumerator *)reverseObjectEnumerator;
+
+@end /* EOExpressionArray */
+
+
+@interface NSObject (EOExpression)
+- (NSString*)expressionValueForContext:(id<EOExpressionContext>)context;
+@end
+
+#endif /* __EOExpressionArray_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOFExceptions.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOFExceptions_h__
+#define __EOFExceptions_h__
+
+#import <Foundation/NSException.h>
+
+@class NSString;
+@class EOEntity;
+@class EORelationship;
+@class EOAdaptorChannel;
+
+@interface EOFException : NSException
+@end
+
+@interface ObjectNotAvailableException : EOFException
+- initWithEntity:entity andPrimaryKey:key;
+@end
+
+@interface PropertyDefinitionException : EOFException
+@end
+
+@interface DestinationEntityDoesntMatchDefinitionException
+ : PropertyDefinitionException
+- initForDestination:(EOEntity*)destinationEntity
+ andDefinition:(NSString*)definition
+ relationship:(EORelationship*)relationship;
+@end
+
+@interface InvalidNameException : PropertyDefinitionException
+- initWithName:(NSString*)name;
+@end
+
+@interface InvalidPropertyException : PropertyDefinitionException
+- initWithName:propertyNamed entity:currentEntity;
+@end
+
+@interface RelationshipMustBeToOneException : PropertyDefinitionException
+- initWithName:propertyNamed entity:currentEntity;
+@end
+
+@interface InvalidValueTypeException : PropertyDefinitionException
+- initWithType:type;
+@end
+
+@interface InvalidAttributeException : EOFException
+@end
+
+@interface InvalidQualifierException : EOFException
+@end
+
+@interface EOAdaptorException : EOFException
+@end
+
+@interface CannotFindAdaptorBundleException : EOAdaptorException
+@end
+
+@interface InvalidAdaptorBundleException : EOAdaptorException
+@end
+
+@interface InvalidAdaptorStateException : EOAdaptorException
+{
+ id adaptor;
+}
++ exceptionWithAdaptor:(id)adaptor;
+@end
+
+@interface DataTypeMappingNotSupportedException : EOAdaptorException
+@end
+
+@interface ChannelIsNotOpenedException : InvalidAdaptorStateException
+@end
+
+@interface AdaptorIsFetchingException : InvalidAdaptorStateException
+@end
+
+@interface AdaptorIsNotFetchingException : InvalidAdaptorStateException
+@end
+
+@interface NoTransactionInProgressException : InvalidAdaptorStateException
+@end
+
+@interface TooManyOpenedChannelsException : EOAdaptorException
+@end
+
+#endif /* __EOFExceptions_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+// $Id: EOFault.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOFault_h__
+#define __EOFault_h__
+
+#import <Foundation/NSObject.h>
+
+@class NSArray, NSDictionary, NSString, NSMethodSignature;
+
+@class EOFaultHandler;
+
+@interface EOFault
+{
+ Class isa;
+ EOFaultHandler *faultResolver;
+}
+
++ (void)makeObjectIntoFault:(id)_object withHandler:(EOFaultHandler *)_handler;
++ (EOFaultHandler *)handlerForFault:(id)_fault;
+
+/* Inquire about a fault */
+
++ (BOOL)isFault:(id)object;
++ (BOOL)isFault;
+- (BOOL)isFault;
++ (void)clearFault:(id)fault;
+
++ (Class)targetClassForFault:fault;
+
+/* Non-Faulting Instance methods */
+
+- (Class)superclass;
+- (Class)class;
++ (Class)class;
+- (BOOL)isKindOfClass:(Class)aClass;
+- (BOOL)isMemberOfClass:(Class)aClass;
+- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
+- (BOOL)respondsToSelector:(SEL)aSelector;
+
++ (id)self;
+
+- (void)dealloc;
+- retain;
+- (void)release;
+- autorelease;
+- (unsigned)retainCount;
+- (NSZone*)zone;
+
+- (BOOL)isProxy;
+- (BOOL)isGarbageCollectable;
+- (NSString *)description;
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector;
+
+@end /* EOFault */
+
+#include <GDLAccess/EOFaultHandler.h>
+
+#endif /* __EOFault_h__ */
--- /dev/null
+// $Id: EOFaultHandler.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOFaultHandler_h__
+#define __EOFaultHandler_h__
+
+#import <Foundation/NSObject.h>
+
+@class NSInvocation, NSMethodSignature;
+@class EOFault;
+
+@interface EOFaultHandler : NSObject
+{
+@public
+ int faultReferences;
+ void *extraData; /* saved ivars overridden by 'faultHandler' ivar */
+ Class targetClass;
+ NSZone *zone;
+}
+
+- (Class)targetClass;
+- (void *)extraData;
+- (void)setTargetClass:(Class)_class extraData:(void *)_extraData;
+
+/* firing */
+
+- (BOOL)shouldPerformInvocation:(NSInvocation *)_invocation;
+- (void)faultWillFire:(EOFault *)_fault;
+- (void)completeInitializationOfObject:(id)_object;
+
+/* fault reflection */
+
+- (Class)classForFault:(EOFault *)_fault;
+- (BOOL)respondsToSelector:(SEL)_selector forFault:(EOFault *)_fault;
+- (BOOL)conformsToProtocol:(Protocol *)_protocol forFault:(EOFault *)_fault;
+- (BOOL)isKindOfClass:(Class)_class forFault:(EOFault *)_fault;
+- (BOOL)isMemberOfClass:(Class)_class forFault:(EOFault *)_fault;
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector
+ forFault:(EOFault *)_fault;
+
+/* description */
+
+- (NSString *)descriptionForObject:(id)_fault;
+
+@end /* EOFaultHandler */
+
+#endif /* __EOFaultHandler_h__ */
--- /dev/null
+// $Id: EOGenericRecord.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __eoaccess_EOGenericRecord_H__
+#define __eoaccess_EOGenericRecord_H__
+
+#import <EOControl/EOGenericRecord.h>
+
+@class NSDictionary;
+@class EOEntity;
+
+@interface EOGenericRecord(EOAccess)
+
+// Initializing new instances
+
+- (id)initWithPrimaryKey:(NSDictionary *)aKey entity:(EOEntity *)anEntity;
+
+// Getting the associated entity
+
+- (EOEntity *)entity;
+
+@end
+
+/*
+ * Informal protocol. NOT implemented by NSObject.
+ * Before sending one of this messages the caller must
+ * check if the object responds to them.
+ */
+
+@interface NSObject(EOGenericRecord)
+
+/*
+ * Initialize an new instance of an object.
+ * If an enterprise object does not respond
+ * to this method it will receive -init.
+ */
+- (id)initWithPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity;
+
+/*
+ * Determines the entity of user defined objects,
+ * when more than one entity uses the same class for its objects.
+ */
+- (EOEntity *)entity;
+
+/*
+ * Determine the class for object based on its fetched row.
+ * The returned class *must* be a subclass of the class that
+ * receives this method.
+ */
++ (Class)classForEntity:(EOEntity *)entity values:(NSDictionary *)values;
+
+@end
+
+#endif /* __eoaccess_EOGenericRecord_H__ */
+
--- /dev/null
+// $Id: EOJoinTypes.h 1 2004-08-20 10:38:46Z znek $
+
+typedef enum {
+ EOInnerJoin = 0,
+ EOFullOuterJoin,
+ EOLeftOuterJoin,
+ EORightOuterJoin
+} EOJoinSemantic;
+
+typedef enum {
+ EOJoinEqualTo = 0,
+ EOJoinNotEqualTo,
+ EOJoinGreaterThan,
+ EOJoinGreaterThanOrEqualTo,
+ EOJoinLessThan,
+ EOJoinLessThanOrEqualTo
+} EOJoinOperator;
+
+@class EOJoin;
--- /dev/null
+/*
+ EOKeySortOrdering.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSArray.h>
+
+@interface EOKeySortOrdering : NSObject
+{
+ NSString* key;
+ NSComparisonResult ordering;
+}
+
++ keyOrderingWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering;
+- initWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering;
+- (NSString*)key;
+- (NSComparisonResult)ordering;
+@end
+
+@interface NSArray(EOKeyBasedSorting)
+- (NSArray*)sortedArrayUsingKeyOrderArray:(NSArray*)orderArray;
+@end
+
+@interface NSMutableArray(EOKeyBasedSorting)
+- (void)sortUsingKeyOrderArray:(NSArray *)orderArray;
+@end
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOModel.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOModel_h__
+#define __EOModel_h__
+
+#import <Foundation/NSString.h>
+
+@class EOEntity;
+
+@interface EOModel : NSObject
+{
+ NSString *name;
+ NSString *path;
+ NSString *adaptorName;
+ NSString *adaptorClassName;
+ NSDictionary *connectionDictionary;
+ NSDictionary *pkeyGeneratorDictionary;
+ NSDictionary *userDictionary;
+
+ NSArray *entities; // values with EOEntities
+ NSMutableDictionary *entitiesByName; // name/value with EOEntity
+ NSMutableDictionary *entitiesByClassName; // class name/value with EOEntity
+
+ struct {
+ BOOL createsMutableObjects:1;
+ BOOL errors:1;
+ } flags;
+}
+
+/* Searching for a model file */
++ (NSString*)findPathForModelNamed:(NSString*)name;
+
+/* Initializing instances */
+- (id)initWithContentsOfFile:(NSString*)filename;
+- (id)initWithPropertyList:propertyList;
+- (id)initWithName:(NSString*)name;
+
+/* Getting the filename */
+- (NSString*)path;
+
+/* Getting a property list representation */
+- (id)modelAsPropertyList;
+
+/* Getting the name */
+- (NSString*)name;
+
+/* Using entities */
+- (BOOL)addEntity:(EOEntity *)entity;
+- (void)removeEntityNamed:(NSString *)name;
+- (EOEntity *)entityNamed:(NSString *)name;
+- (NSArray *)entities;
+
+/* Checking references */
+- (NSArray *)referencesToProperty:(id)property;
+
+/* Getting an object's entity */
+- (EOEntity *)entityForObject:(id)object;
+
+/* Adding model information */
+- (BOOL)incorporateModel:(EOModel *)model;
+
+/* Accessing the adaptor bundle */
+- (void)setAdaptorName:(NSString *)adaptorName;
+- (NSString *)adaptorName;
+
+/* Setting and getting the adaptor class name. */
+- (void)setAdaptorClassName:(NSString *)adaptorClassName;
+- (NSString *)adaptorClassName;
+
+/* Accessing the connection dictionary */
+- (void)setConnectionDictionary:(NSDictionary *)connectionDictionary;
+- (NSDictionary *)connectionDictionary;
+
+/* Accessing the pkey generator dictionary */
+- (void)setPkeyGeneratorDictionary:(NSDictionary *)connectionDictionary;
+- (NSDictionary *)pkeyGeneratorDictionary;
+
+/* Accessing the user dictionary */
+- (void)setUserDictionary:(NSDictionary *)dictionary;
+- (NSDictionary *)userDictionary;
+
+@end
+
+
+@interface EOModel (EOModelPrivate)
+
+- (void)setCreateMutableObjects:(BOOL)flag;
+- (BOOL)createsMutableObjects;
+
+- (void)errorInReading;
+
+@end /* EOModel (EOModelPrivate) */
+
+@interface EOModel(NewInEOF2)
+
+- (void)loadAllModelObjects;
+
+@end
+
+#endif /* __EOModel_h__ */
--- /dev/null
+// $Id: EOModelGroup.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOAccess_EOModelGroup_H__
+#define __EOAccess_EOModelGroup_H__
+
+#import <Foundation/NSObject.h>
+
+@class NSDictionary;
+@class EOGlobalID, EOFetchSpecification;
+@class EOModelGroup, EOModel, EOEntity, EORelationship;
+
+@protocol EOModelGroupClassDelegation < NSObject >
+
+- (EOModelGroup *)defaultModelGroup;
+
+@end
+
+@protocol EOModelGroupDelegation < NSObject >
+
+- (Class)entity:(EOEntity *)_entity
+ classForObjectWithGlobalID:(EOGlobalID *)_oid;
+
+- (Class)entity:(EOEntity *)_entity
+ failedToLookupClassNamed:(NSString *)_className;
+
+- (EOEntity *)relationship:(EORelationship *)_relship
+ failedToLookupDestinationNamed:(NSString *)_entityName;
+
+- (EOEntity *)subEntityForEntity:(EOEntity *)_entity
+ primaryKey:(NSDictionary *)_pkey
+ isFinal:(BOOL *)_flag;
+
+- (EOModel *)modelGroup:(EOModelGroup *)_group
+ entityNamed:(NSString *)_name;
+
+- (EORelationship *)entity:(EOEntity *)_entity
+ relationshipForRow:(NSDictionary *)_row
+ relationship:(EORelationship *)_relship;
+
+@end
+
+@class NSArray, NSMutableDictionary;
+
+@interface EOModelGroup : NSObject
+{
+ NSMutableDictionary *nameToModel;
+ id<EOModelGroupDelegation> delegate; /* non-retained */
+}
+
++ (void)setDefaultGroup:(EOModelGroup *)_group;
++ (EOModelGroup *)defaultGroup;
+
++ (EOModelGroup *)globalModelGroup;
+
+/* class delegate */
+
++ (void)setClassDelegate:(id<EOModelGroupClassDelegation>)_delegate;
++ (id<EOModelGroupClassDelegation>)classDelegate;
+
+/* instance delegate */
+
+- (void)setDelegate:(id<EOModelGroupDelegation>)_delegate;
+- (id<EOModelGroupDelegation>)delegate;
+
+/* models */
+
+- (void)addModel:(EOModel *)_model;
+- (void)removeModel:(EOModel *)_model;
+
+- (EOModel *)modelNamed:(NSString *)_name;
+- (NSArray *)modelNames;
+- (NSArray *)models;
+- (EOModel *)modelWithPath:(NSString *)_path;
+- (EOModel *)addModelWithFile:(NSString *)_path;
+
+- (void)loadAllModelObjects;
+
+/* entities */
+
+- (EOEntity *)entityForObject:(id)_object;
+- (EOEntity *)entityNamed:(NSString *)_name;
+
+- (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name
+ entityNamed:(NSString *)_entityName;
+
+@end
+
+#endif /* __EOAccess_EOModelGroup_H__ */
--- /dev/null
+// $Id: EONull.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __eoaccess_EONull_H__
+#define __eoaccess_EONull_H__
+
+#import <EOControl/EONull.h>
+
+#endif /* __eoaccess_EONull_H__ */
--- /dev/null
+/*
+ EOObjectUniquer.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOObjectUniquer_h__
+#define __EOObjectUniquer_h__
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSMapTable.h>
+
+@class EOEntity;
+@class NSDictionary;
+@class NSArray;
+
+typedef struct _EOUniquerRecord {
+ int refCount;
+ id pkey;
+ id entity;
+ id object;
+ id snapshot;
+} EOUniquerRecord;
+
+@interface EOObjectUniquer : NSObject
+{
+@protected
+ NSMapTable *primaryKeyToRec;
+ NSMapTable *objectsToRec;
+ struct _EOUniquerRecord *keyRecord;
+}
+
+// Initializing a uniquing dictionary
+- init;
+
+// Transfer self to parent
+- (void)transferTo:(EOObjectUniquer*)dest
+ objects:(BOOL)isObj andSnapshots:(BOOL)isSnap;
+
+// Handling objects
+- (void)forgetObject:(id)anObj;
+- (void)forgetAllObjects;
+- (void)forgetAllSnapshots;
+
+- (id)objectForPrimaryKey:(NSDictionary *)aKey
+ entity:(EOEntity *)anEntity;
+
+- (EOUniquerRecord *)recordForObject:(id)anObj;
+
+- (void)recordObject:(id)anObj
+ primaryKey:(NSDictionary *)aKey
+ entity:(EOEntity *)anEntity
+ snapshot:(NSDictionary *)aSnapshot;
+
+@end /* EOObjectUniquer */
+
+#endif /* __EOObjectUniquer_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOPrimaryKeyDictionary.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOPrimaryKeyDictionary_h__
+#define __EOPrimaryKeyDictionary_h__
+
+#import <Foundation/NSDictionary.h>
+
+@interface EOPrimaryKeyDictionary : NSDictionary
+{
+ @public
+ unsigned fastHash;
+ @protected
+}
+
++ dictionaryWithKeys:(NSArray*)keys fromDictionary:(NSDictionary*)dict;
++ dictionaryWithObject:(id)object forKey:(id)key;
+- (unsigned)fastHash;
+- (BOOL)fastIsEqual:aDict;
+@end /* EOPrimaryKeyDictionary */
+
+#endif /* __EOPrimaryKeyDictionary_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOQualifierScanner.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Helge Hess <helge.hess@mdlink.de>
+ Date: September 1996
+ November 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOQualifierScanner.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __EOAccess_EOQualifierScanner_H__
+#define __EOAccess_EOQualifierScanner_H__
+
+#if !LIB_FOUNDATION_LIBRARY
+# import "DefaultScannerHandler.h"
+#else
+# import <extensions/DefaultScannerHandler.h>
+#endif
+
+@class EOEntity;
+
+@interface EOQualifierScannerHandler : DefaultScannerHandler
+{
+ EOEntity *entity;
+}
+
+- (void)setEntity:(EOEntity *)entity;
+
+@end
+
+@interface EOQualifierEnumScannerHandler : DefaultEnumScannerHandler
+{
+ EOEntity *entity;
+}
+
+- (void)setEntity:(EOEntity *)entity;
+
+@end
+
+#endif /* __EOAccess_EOQualifierScanner_H__ */
--- /dev/null
+/*
+ EOQuotedExpression.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOQuotedExpression_h__
+#define __EOQuotedExpression_h__
+
+#import <GDLAccess/EOExpressionArray.h>
+
+@class NSString;
+
+@interface EOQuotedExpression : NSObject <NSCopying>
+{
+ id expression;
+ NSString *quote;
+ NSString *escape;
+}
+
+- (id)expressionValueForContext:(id<EOExpressionContext>)context;
+
+- (id)initWithExpression:(id)expression
+ quote:(NSString *)quote
+ escape:(NSString *)escape;
+
+@end
+
+#endif /* __EOQuotedExpression_h__ */
--- /dev/null
+/*
+*/
+
+#ifndef __EORecordDictionary_h__
+#define __EORecordDictionary_h__
+
+#import <Foundation/NSDictionary.h>
+
+typedef struct _EORecordDictionaryEntry {
+ unsigned hash;
+ id key;
+ id value;
+} EORecordDictionaryEntry;
+
+@interface EORecordDictionary : NSDictionary
+{
+ unsigned char count;
+ EORecordDictionaryEntry entries[1];
+}
+
+/* Allocating and Initializing an Dictionary */
+- (id)initWithObjects:(id*)objects forKeys:(id*)keys
+ count:(unsigned int)count;
+- (id)initWithDictionary:(NSDictionary*)dictionary;
+
+/* Accessing keys and values */
+- (id)objectForKey:(id)aKey;
+- (unsigned int)count;
+- (NSEnumerator *)keyEnumerator;
+
+@end /* EORecordDictionary */
+
+#import <Foundation/NSEnumerator.h>
+
+@interface _EORecordDictionaryKeyEnumerator : NSEnumerator
+{
+ NSDictionary *dict;
+ EORecordDictionaryEntry *currentEntry;
+ unsigned char count;
+}
+
+- (id)initWithDictionary:(EORecordDictionary *)_dict
+ firstEntry:(EORecordDictionaryEntry *)_firstEntry
+ count:(unsigned char)_count;
+
+- (id)nextObject;
+
+@end
+
+#endif
--- /dev/null
+/*
+ EORelationship.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EORelationship_h__
+#define __EORelationship_h__
+
+#import <Foundation/NSString.h>
+#import <GDLAccess/EOJoinTypes.h>
+
+@class NSString, NSDictionary, NSException;
+@class EOModel, EOEntity, EOAttribute;
+
+@interface EORelationship : NSObject
+{
+ NSString *name;
+ NSString *definition;
+ NSDictionary *userDictionary;
+
+ /* Garbage collectable objects */
+ EOEntity *entity; /* non-retained */
+ EOEntity *destinationEntity; /* non-retained */
+
+ /* Computed values */
+ NSMutableArray *componentRelationships;
+
+ struct {
+ BOOL isFlattened:1;
+ BOOL isToMany:1;
+ BOOL createsMutableObjects:1;
+ BOOL isMandatory:1;
+ } flags;
+
+ // EOJoin
+
+ EOAttribute *sourceAttribute;
+ EOAttribute *destinationAttribute;
+}
+
+/* Initializing instances */
+- (id)initWithName:(NSString*)name;
+
+/* Accessing the name */
+- (BOOL)setName:(NSString*)name;
+- (NSString*)name;
++ (BOOL)isValidName:(NSString*)name;
+
+/* Using joins */
+
+- (NSArray*)joins;
+
+/* Convering source row in destination row */
+- (NSDictionary*)foreignKeyForRow:(NSDictionary*)row;
+
+/* Accessing the definition */
+- (NSArray*)componentRelationships;
+- (void)setDefinition:(NSString*)definition;
+- (NSString*)definition;
+
+/* Accessing the entities joined */
+- (void)setEntity:(EOEntity*)entity;
+- (EOEntity*)entity;
+- (void)resetEntities;
+- (BOOL)hasEntity;
+- (BOOL)hasDestinationEntity;
+- (EOEntity*)destinationEntity;
+
+/* Checking type */
+- (BOOL)isCompound; // always NO (no compound joins supported)
+- (BOOL)isFlattened;
+
+/* Accessing to-many property */
+- (BOOL)setToMany:(BOOL)flag;
+- (BOOL)isToMany;
+
+/* Checking references */
+- (BOOL)referencesProperty:(id)property;
+
+/* Accessing the user dictionary */
+- (void)setUserDictionary:(NSDictionary*)dictionary;
+- (NSDictionary*)userDictionary;
+
+@end
+
+@interface EORelationship(EOJoin)
+
+- (void)loadJoinPropertyList:(id)propertyList;
+
+/* Accessing join properties */
+- (void)setDestinationAttribute:(EOAttribute*)attribute;
+- (EOAttribute*)destinationAttribute;
+- (void)setSourceAttribute:(EOAttribute*)attribute;
+- (EOAttribute*)sourceAttribute;
+- (EORelationship*)relationship;
+
+@end
+
+@interface EORelationship (EORelationshipPrivate)
+
++ (EORelationship*)relationshipFromPropertyList:(id)propertyList
+ model:(EOModel*)model;
+- (void)replaceStringsWithObjects;
+- (void)initFlattenedRelationship;
+
+- (id)propertyList;
+
+- (void)setCreateMutableObjects:(BOOL)flag;
+- (BOOL)createsMutableObjects;
+
+@end /* EORelationship (EORelationshipPrivate) */
+
+@class NSMutableDictionary;
+
+@interface EORelationship(PropertyListCoding)
+
+- (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist;
+
+@end
+
+@class NSException;
+
+@interface EORelationship(EOF2Additions)
+
+/* constraints */
+
+- (void)setIsMandatory:(BOOL)_flag;
+- (BOOL)isMandatory;
+
+- (NSException *)validateValue:(id *)_value;
+
+@end
+
+#endif /* __EORelationship_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOSQLExpression.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: September 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOSQLExpression_h__
+#define __EOSQLExpression_h__
+
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSArray.h>
+
+#import <GDLAccess/EOExpressionArray.h>
+#import <GDLAccess/EOJoinTypes.h>
+
+@class EOAdaptor;
+@class EOAdaptorChannel;
+@class EOEntity;
+@class EOSQLQualifier;
+
+extern NSString *EOBindVariableNameKey;
+extern NSString *EOBindVariablePlaceHolderKey;
+extern NSString *EOBindVariableAttributeKey;
+extern NSString *EOBindVariableValueKey;
+
+@interface EOSQLExpression : NSObject <EOExpressionContext>
+{
+ EOEntity *entity;
+ EOAdaptor *adaptor;
+ NSMutableDictionary *entitiesAndPropertiesAliases;
+ NSMutableArray *fromListEntities;
+ NSMutableString *content;
+
+ /* new in EOF2 */
+ NSString *whereClauseString;
+ NSMutableString *listString;
+ NSMutableArray *bindings;
+}
+
+/* Building SQL expressions */
+
++ (id)deleteExpressionWithQualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel *)channel;
++ (id)insertExpressionForRow:(NSDictionary *)row
+ entity:(EOEntity *)entity
+ channel:(EOAdaptorChannel *)channel;
++ (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel;
++ (id)updateExpressionForRow:(NSDictionary *)row
+ qualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel *)channel;
+
+- (id)deleteExpressionWithQualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel *)channel;
+- (id)insertExpressionForRow:(NSDictionary *)row
+ entity:(EOEntity *)entity
+ channel:(EOAdaptorChannel *)channel;
+- (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel;
+- (id)updateExpressionForRow:(NSDictionary *)row
+ qualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel *)channel;
+
+/* factory classes */
+
++ (Class)selectExpressionClass;
++ (Class)insertExpressionClass;
++ (Class)deleteExpressionClass;
++ (Class)updateExpressionClass;
+
+/* Getting the adaptor */
+- (EOAdaptor *)adaptor;
+
+// Private methods.
+
+/* Creating components for the SELECT operation */
+- (NSString *)selectListWithAttributes:(NSArray *)attributes
+ qualifier:(EOSQLQualifier *)qualifier;
+- (NSString *)fromClause;
+- (NSString *)whereClauseForQualifier:(EOSQLQualifier *)qualifier;
+- (NSString *)joinExpressionForRelationshipPaths:(NSArray *)relationshipPaths;
+- (NSString *)lockClause;
+- (NSString *)orderByClauseForFetchOrder:(NSArray *)fetchOrder;
+
+/* Creating components for the UPDATE operation */
+- (id)updateListForRow:(NSDictionary *)row;
+
+/* Creating components for the INSERT operation */
+- (id)columnListForRow:(NSDictionary *)row;
+- (id)valueListForRow:(NSDictionary *)row;
+
+/* Final initialization */
+- (id)finishBuildingExpression;
+
+/* Caching aliases */
+- (NSArray *)relationshipPathsForAttributes:(NSArray *)attributes
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder;
+
+/* Getting the entity */
+- (EOEntity *)entity;
+
+/* Getting the expression value of an attribute in a given context. This
+ method is used by the expressionValueForAttribute: method. */
+- (NSString *)expressionValueForAttribute:(EOAttribute *)attribute
+ context:context;
+
+@end
+
+@class NSArray;
+@class EOFetchSpecification, EOKeyComparisonQualifier, EOKeyValueQualifier;
+@class EOQualifier;
+
+@interface EOSQLExpression(NewInEOF2)
+
++ (EOSQLExpression *)selectStatementForAttributes:(NSArray *)_attributes
+ lock:(BOOL)_flag
+ fetchSpecification:(EOFetchSpecification *)_fspec
+ entity:(EOEntity *)_entity;
++ (EOSQLExpression *)expressionForString:(NSString *)_sql;
+
+/* accessors */
+
+- (void)setStatement:(NSString *)_stmt;
+- (NSString *)statement;
+- (NSString *)whereClauseString;
+
+/* tables */
+
+- (NSString *)tableListWithRootEntity:(EOEntity *)_entity;
+
+/* assembly */
+
+- (NSString *)assembleDeleteStatementWithQualifier:(EOQualifier *)_qualifier
+ tableList:(NSString *)_tableList
+ whereClause:(NSString *)_whereClause;
+
+- (NSString *)assembleInsertStatementWithRow:(NSDictionary *)_row
+ tableList:(NSString *)_tables
+ columnList:(NSString *)_columns
+ valueList:(NSString *)_values;
+
+- (NSString *)assembleSelectStatementWithAttributes:(NSArray *)_attributes
+ lock:(BOOL)_lock
+ qualifier:(EOQualifier *)_qualifier
+ fetchOrder:(NSArray *)_fetchOrder
+ selectString:(NSString *)_selectString
+ columnList:(NSString *)_columns
+ tableList:(NSString *)_tables
+ whereClause:(NSString *)_whereClause
+ joinClause:(NSString *)_joinClause
+ orderByClause:(NSString *)_orderByClause
+ lockClause:(NSString *)_lockClause;
+
+- (NSString *)assembleUpdateStatementWithRow:(NSDictionary *)_row
+ qualifier:(EOQualifier *)_qualifier
+ tableList:(NSString *)_tables
+ updateList:(NSString *)_updates
+ whereClause:(NSString *)_whereClause;
+
+- (NSString *)assembleJoinClauseWithLeftName:(NSString *)_leftName
+ rightName:(NSString *)_rightName
+ joinSemantic:(EOJoinSemantic)_semantic;
+
+/* bind variables */
+
+- (BOOL)mustUseBindVariableForAttribute:(EOAttribute *)_attr;
+- (BOOL)shouldUseBindVariableForAttribute:(EOAttribute *)_attr;
++ (BOOL)useBindVariables;
+- (NSMutableDictionary *)bindVariableDictionaryForAttribute:(EOAttribute *)_attr
+ value:(id)_value;
+- (void)addBindVariableDictionary:(NSMutableDictionary *)_dictionary;
+- (NSArray *)bindVariableDictionaries;
+
+/* values */
+
++ (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute;
+- (NSString *)sqlStringForValue:(id)_value attributeNamed:(NSString *)_attrName;
++ (NSString *)sqlPatternFromShellPattern:(NSString *)_pattern;
+
+/* attributes */
+
+- (NSString *)sqlStringForAttribute:(EOAttribute *)_attribute;
+- (NSString *)sqlStringForAttributePath:(NSString *)_attrPath;
+- (NSString *)sqlStringForAttributeNamed:(NSString *)_attrName;
+
+/* SQL formats */
+
++ (NSString *)formatSQLString:(NSString *)_sqlString format:(NSString *)_fmt;
+
+/* qualifier operators */
+
+- (NSString *)sqlStringForSelector:(SEL)_selector value:(id)_value;
+
+/* qualifiers */
+
+- (NSString *)sqlStringForKeyComparisonQualifier:(EOKeyComparisonQualifier *)_q;
+- (NSString *)sqlStringForKeyValueQualifier:(EOKeyValueQualifier *)_q;
+- (NSString *)sqlStringForNegatedQualifier:(EOQualifier *)_q;
+- (NSString *)sqlStringForConjoinedQualifiers:(NSArray *)_qs;
+- (NSString *)sqlStringForDisjoinedQualifiers:(NSArray *)_qs;
+
+/* list strings */
+
+- (NSMutableString *)listString;
+- (void)appendItem:(NSString *)_itemString toListString:(NSMutableString *)_lstr;
+
+/* deletes */
+
+- (void)prepareDeleteExpressionForQualifier:(EOQualifier *)_qualifier;
+
+/* updates */
+
+- (void)addUpdateListAttribute:(EOAttribute *)_attr value:(NSString *)_value;
+
+- (void)prepareUpdateExpressionWithRow:(NSDictionary *)_row
+ qualifier:(EOQualifier *)_qualifier;
+
+@end
+
+/* Private subclasses used by EOSQLExpression. */
+
+@interface EOSelectSQLExpression : EOSQLExpression
+@end
+
+@interface EOUpdateSQLExpression : EOSQLExpression
+@end
+
+@interface EOInsertSQLExpression : EOSQLExpression
+@end
+
+@interface EODeleteSQLExpression : EOSQLExpression
+@end
+
+#endif /* __EOSQLExpression_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOSQLQualifier.h
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Helge Hess <helge.hess@mdlink.de>
+ Date: September 1996
+ November 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EOSQLQualifier_h__
+#define __EOSQLQualifier_h__
+
+#import <EOControl/EOQualifier.h>
+
+#import <GDLAccess/EOExpressionArray.h>
+
+@class NSDictionary, NSString, NSMutableSet;
+@class EOEntity, EORelationship, EOExpressionArray, EOSQLQualifier;
+@class EOSQLExpression;
+
+@protocol EOQualifierSQLGeneration
+
+- (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr;
+- (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity;
+
+@end
+
+@interface EOSQLQualifier : EOQualifier < NSCopying >
+{
+ /* TODO: these should be GCMutableSet */
+ NSMutableSet *relationshipPaths;
+ NSMutableSet *additionalEntities;
+
+ /* Garbage collectable objects */
+ EOEntity *entity;
+ EOExpressionArray *content;
+ BOOL usesDistinct;
+}
+
+/* Combining qualifiers */
+- (void)negate;
+- (void)conjoinWithQualifier:(EOSQLQualifier*)qualifier;
+- (void)disjoinWithQualifier:(EOSQLQualifier*)qualifier;
+
+/* Getting the entity */
+- (EOEntity *)entity;
+
+/* Checking the definition */
+- (BOOL)isEmpty;
+
+/* Accessing the distinct selection */
+- (void)setUsesDistinct:(BOOL)flag;
+- (BOOL)usesDistinct;
+
+/* Accessing the relationships referred within qualifier */
+- (NSMutableSet*)relationshipPaths;
+- (NSMutableSet*)additionalEntities;
+
+/* Getting the expression value */
+- (NSString*)expressionValueForContext:(id<EOExpressionContext>)ctx;
+
+/* Private methods */
+- (void)_computeRelationshipPaths:(NSArray *)_relationshipPaths;
+- (void)_computeRelationshipPaths;
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity;
+
+@end
+
+@interface EOSQLQualifier(QualifierCreation)
+
+- (id)initWithEntity:(EOEntity *)_entity
+ qualifierFormat:(NSString *)_qualifierFormat, ...;
+
+- (id)initWithEntity:(EOEntity *)_entity
+ qualifierFormat:(NSString *)_qualifierFormat
+ argumentsArray:(NSArray *)_args;
+
+/* Creating instances */
+
++ (EOSQLQualifier *)qualifierForRow:(NSDictionary *)row
+ entity:(EOEntity *)entity;
+
++ (EOSQLQualifier *)qualifierForPrimaryKey:(NSDictionary *)key
+ entity:(EOEntity *)entity;
+
++ (EOSQLQualifier *)qualifierForRow:(NSDictionary *)row
+ relationship:(EORelationship *)relationship;
+
++ (EOSQLQualifier *)qualifierForObject:(id)sourceObject
+ relationship:(EORelationship *)relationship;
+
+@end
+
+@interface EOQualifier(SQLQualifier)
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity;
+@end
+
+@interface EOAndQualifier(SQLGeneration) < EOQualifierSQLGeneration >
+@end
+
+@interface EOOrQualifier(SQLGeneration) < EOQualifierSQLGeneration >
+@end
+
+@interface EONotQualifier(SQLGeneration) < EOQualifierSQLGeneration >
+@end
+
+@interface EOKeyValueQualifier(SQLGeneration) < EOQualifierSQLGeneration >
+@end
+
+@interface EOKeyComparisonQualifier(SQLGeneration) < EOQualifierSQLGeneration >
+@end
+
+#endif /* __EOSQLQualifier_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+// $Id: GDLAccess.h 1 2004-08-20 10:38:46Z znek $
+
+#import <GDLAccess/EOAccess.h>
--- /dev/null
+// $Id: NSObject+EONullInit.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __GDLAccess_NSObject_EONull_H__
+#define __GDLAccess_NSObject_EONull_H__
+
+#import <Foundation/NSObject.h>
+#import <GDLAccess/EONull.h>
+
+@class EOEntity;
+
+@interface NSObject(EONullInit)
+
+- (void)setAllAttributesToEONull:(EOEntity *)_entity;
+- (void)setAllAttributesToEONull; // assume the object respondsTo: entity
+
+@end
+
+#endif /* __GDLAccess_NSObject_EONull_H__ */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOAdaptor.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOAdaptor.h"
+#import "EOAdaptorChannel.h"
+#import "EOAdaptorContext.h"
+#import "EOAttribute.h"
+#import "EOFExceptions.h"
+#import "EOModel.h"
+#import "EOSQLExpression.h"
+
+
+@implementation EOAdaptor
+
++ (id)adaptorWithModel:(EOModel*)_model {
+ /* Check first to see if the adaptor class exists in the running program
+ by testing the existence of [_model adaptorClassName]. */
+ NSString *adaptorName = [_model adaptorName];
+ Class adaptorClass = NSClassFromString([_model adaptorClassName]);
+ id adaptor;
+
+ adaptor = adaptorClass
+ ? AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName])
+ : [self adaptorWithName:adaptorName];
+
+ [adaptor setModel:_model];
+ return adaptor;
+}
+
++ (id)adaptorWithName:(NSString *)adaptorName {
+ int i, count;
+ NSBundle *bundle = [NSBundle mainBundle];
+ NSString *adaptorBundlePath = nil;
+ NSArray *adaptorsPath = nil;
+ NSMutableArray *paths = nil;
+ Class adaptorClass = Nil;
+ NSProcessInfo *pInfo = nil;
+ NSDictionary *env = nil;
+ NSMutableString *gdl, *user, *local, *system;
+
+ bundle = [NSBundle mainBundle];
+
+ /* Check error */
+ if ((adaptorName == nil) || [adaptorName isEqual:@""])
+ return nil;
+
+ /* Look in application bundle */
+ adaptorBundlePath =
+ [bundle pathForResource:adaptorName ofType:@"gdladaptor"];
+
+ /* Look in standard paths */
+ if (adaptorBundlePath == nil) {
+ /*
+ The path of where to search for the adaptor files
+ is based upon environment variables.
+ GDL_ADAPTORS_PATH
+ GNUSTEP_USER_ROOT
+ GNUSTEP_LOCAL_ROOT
+ GNUSTEP_SYSTEM_ROOT
+ */
+ pInfo = [NSProcessInfo processInfo];
+ env = [pInfo environment];
+ paths = [NSMutableArray array];
+
+ /* GDL_ADAPTORS_PATH is a separated list of paths */
+ gdl = [env objectForKey: @"GDL_ADAPTORS_PATH"];
+ if (gdl) adaptorsPath = [gdl componentsSeparatedByString:@":"];
+
+ if (adaptorsPath) [paths addObjectsFromArray: adaptorsPath];
+
+ user = AUTORELEASE([[env objectForKey: @"GNUSTEP_USER_ROOT"]
+ mutableCopyWithZone:[self zone]]);
+ [user appendString: @"/Libraries"];
+ if (user) [paths addObject: user];
+
+ local = AUTORELEASE([[env objectForKey: @"GNUSTEP_LOCAL_ROOT"]
+ mutableCopyWithZone:[self zone]]);
+ [local appendString: @"/Libraries"];
+ if (local) [paths addObject: local];
+
+ system = AUTORELEASE([[env objectForKey: @"GNUSTEP_SYSTEM_ROOT"]
+ mutableCopy]);
+ [system appendString: @"/Libraries"];
+ if (system)
+ [paths addObject: system];
+
+ /* Loop through the paths and check each one */
+ for(i = 0, count = [paths count]; i < count; i++) {
+ bundle = [NSBundle bundleWithPath: [paths objectAtIndex:i]];
+ adaptorBundlePath = [bundle pathForResource:adaptorName
+ ofType:@"gdladaptor"
+ inDirectory:@"Adaptors"];
+
+ if((adaptorBundlePath != nil) && [adaptorBundlePath length])
+ break;
+ }
+ }
+
+ /* Make adaptor bundle */
+ bundle = adaptorBundlePath
+ ? [NSBundle bundleWithPath:adaptorBundlePath]
+ : nil;
+
+ /* Check bundle */
+ if (bundle == nil) {
+ NSLog(@"Cannot find adaptor bundle '%@'", adaptorName);
+#if 0
+ [[[[CannotFindAdaptorBundleException alloc]
+ initWithFormat:@"Cannot find adaptor bundle '%@'",
+ adaptorName] autorelease] raise];
+#endif
+ return nil;
+ }
+
+ /* load bundle */
+
+ if (![bundle load]) {
+ NSLog(@"Cannot load adaptor bundle '%@'", adaptorName);
+#if 1
+ [[[[InvalidAdaptorBundleException alloc]
+ initWithFormat:@"Cannot load adaptor bundle '%@'",
+ adaptorName] autorelease] raise];
+#endif
+ return nil;
+ }
+
+ /* Get the adaptor bundle "infoDictionary", and pricipal class, ie. the
+ adaptor class. Other info about the adaptor should be put in the
+ bundle's "Info.plist" file (property list format - see NSBundle class
+ documentation for details about reserved keys in this dictionary
+ property list containing one entry whose key is adaptorClassName. It
+ identifies the actual adaptor class from the bundle. */
+
+ adaptorClass = [bundle principalClass];
+ if (adaptorClass == Nil) {
+ NSLog(@"The adaptor bundle '%@' at '%@' doesn't contain "
+ @"a principal class (infoDict=%@)",
+ adaptorName, [bundle bundlePath], [bundle infoDictionary]);
+
+ [[[InvalidAdaptorBundleException alloc]
+ initWithFormat:@"The adaptor bundle '%@' doesn't contain "
+ @"a principal class (infoDict=%@)",
+ adaptorName, [bundle infoDictionary]]
+ raise];
+ }
+ return AUTORELEASE([[adaptorClass alloc] initWithName:adaptorName]);
+}
+
+- (id)initWithName:(NSString*)_name {
+ ASSIGN(self->name, _name);
+ self->contexts = [[NSMutableArray allocWithZone:[self zone]] init];
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->model);
+ RELEASE(self->name);
+ RELEASE(self->connectionDictionary);
+ RELEASE(self->pkeyGeneratorDictionary);
+ RELEASE(self->contexts);
+ [super dealloc];
+}
+
+/* accessors */
+
+- (void)setConnectionDictionary:(NSDictionary*)_dictionary {
+ if([self hasOpenChannels]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Cannot set the connection dictionary "
+ @"while the adaptor is connected!"];
+ }
+ ASSIGN(self->connectionDictionary, _dictionary);
+ [self->model setConnectionDictionary:_dictionary];
+}
+- (NSDictionary *)connectionDictionary {
+ return self->connectionDictionary;
+}
+- (BOOL)hasValidConnectionDictionary {
+ return NO;
+}
+
+- (EOAdaptorContext*)createAdaptorContext {
+ return AUTORELEASE([[[self adaptorContextClass] alloc]
+ initWithAdaptor:self]);
+}
+- (NSArray *)contexts {
+ NSMutableArray *ma;
+ unsigned i, count;
+
+ if ((count = [self->contexts count]) == 0)
+ return nil;
+
+ ma = [NSMutableArray arrayWithCapacity:count];
+ for (i = 0; i < count; i++)
+ [ma addObject:[[self->contexts objectAtIndex:i] nonretainedObjectValue]];
+
+ return ma;
+}
+
+/* Setting pkey generation info */
+
+- (void)setPkeyGeneratorDictionary:(NSDictionary*)aDictionary {
+ ASSIGN(self->pkeyGeneratorDictionary, aDictionary);
+ [self->model setPkeyGeneratorDictionary:aDictionary];
+}
+- (NSDictionary*)pkeyGeneratorDictionary {
+ return self->pkeyGeneratorDictionary;
+}
+
+// notifications
+
+- (void)contextDidInit:aContext {
+ [self->contexts addObject:[NSValue valueWithNonretainedObject:aContext]];
+}
+
+- (void)contextWillDealloc:aContext {
+ int i;
+
+ for (i = [contexts count]-1; i >= 0; i--) {
+ if ([[contexts objectAtIndex:i] nonretainedObjectValue] == aContext) {
+ [contexts removeObjectAtIndex:i];
+ break;
+ }
+ }
+}
+
+- (BOOL)hasOpenChannels {
+ int i;
+
+ for (i = [contexts count] - 1; i >= 0; i--) {
+ EOAdaptorContext* ctx = [[contexts objectAtIndex:i]
+ nonretainedObjectValue];
+ if ([ctx hasOpenChannels])
+ return YES;
+ }
+ return NO;
+}
+
+- (id)formatAttribute:(EOAttribute *)_attribute {
+ return [_attribute expressionValueForContext:nil];
+}
+
+- (id)formatValue:(id)_value forAttribute:(EOAttribute *)attribute {
+ if (_value == nil) _value = [NSNull null];
+ return [_value expressionValueForContext:nil];
+}
+
+- (void)reportError:(NSString*)error {
+ if(delegateWillReportError) {
+ if([delegate adaptor:self willReportError:error] == NO)
+ return;
+ }
+ NSLog(@"%@ adaptor error: %@", name, error);
+}
+
+- (void)setDelegate:(id)_delegate {
+ self->delegate = _delegate;
+ self->delegateWillReportError
+ = [self->delegate respondsToSelector:
+ @selector(adaptor:willReportError:)];
+}
+
+- (void)setModel:(EOModel *)_model {
+ ASSIGN(self->model, _model);
+ [self setConnectionDictionary:[_model connectionDictionary]];
+ [self setPkeyGeneratorDictionary:[_model pkeyGeneratorDictionary]];
+}
+- (EOModel *)model {
+ return self->model;
+}
+
+- (NSString *)name {
+ return self->name;
+}
+
+- (Class)expressionClass {
+ return [EOSQLExpression class];
+}
+- (Class)adaptorContextClass {
+ return [EOAdaptorContext class];
+}
+- (Class)adaptorChannelClass {
+ return [EOAdaptorChannel class];
+}
+
+- (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
+ return YES;
+}
+- (BOOL)isValidQualifierType:(NSString*)typeName {
+ return NO;
+}
+- (id)delegate {
+ return self->delegate;
+}
+
+// description
+
+- (NSString *)description {
+ return [NSString stringWithFormat:
+ @"<%@[0x%08X]: name=%@ "
+ @"model=%s connection-dict=%s>",
+ NSStringFromClass([self class]), self,
+ [self name],
+ [self model] ? "yes" : "no",
+ [self connectionDictionary] ? "yes" : "no"];
+}
+
+@end /* EOAdaptor */
+
+@implementation EOAdaptor(EOF2Additions)
+
+- (BOOL)canServiceModel:(EOModel *)_model {
+ return YES;
+}
+
+@end
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAdaptorChannel+Attributes.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOAdaptorChannel+Attributes.h"
+#import "EOAdaptorContext.h"
+#import "EOEntity.h"
+#import "EOAdaptor.h"
+#import "EOModel.h"
+
+@implementation EOAdaptorChannel(Attributes)
+
+- (EOEntity *)_entityForTableName:(NSString *)_tableName {
+ EOModel *model = nil;
+ EOEntity *entity = nil;
+
+ if (_tableName == nil || [_tableName length] == 0)
+ return nil;
+
+ model = [[self->adaptorContext adaptor] model];
+
+ if ((entity = [model entityNamed:_tableName]) == nil) {
+ NSEnumerator *enumerator = nil;
+ enumerator = [[model entities] objectEnumerator];
+ while ((entity = [enumerator nextObject])) {
+ if ([[entity externalName] isEqualToString:_tableName])
+ break;
+ }
+ }
+ if (entity == nil) {
+ model = [self describeModelWithTableNames:
+ [NSArray arrayWithObject:_tableName]];
+
+ if ((entity = [model entityNamed:_tableName]) == nil) {
+ NSEnumerator *enumerator = nil;
+ enumerator = [[model entities] objectEnumerator];
+ while ((entity = [enumerator nextObject])) {
+ if ([[entity externalName] isEqualToString:_tableName])
+ break;
+ }
+ }
+ }
+ return entity;
+}
+
+- (NSArray *)attributesForTableName:(NSString *)_tableName {
+ return [[self _entityForTableName:_tableName] attributes];
+}
+
+- (NSArray *)primaryKeyAttributesForTableName:(NSString *)_tableName {
+ return [[self _entityForTableName:_tableName] primaryKeyAttributes];
+}
+
+@end /* EOAdaptorChannel(Attributes) */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOAdaptorChannel.h"
+#import "EOAttribute.h"
+#import "EOAdaptor.h"
+#import "EOAdaptorContext.h"
+#import "EOSQLExpression.h"
+#import "EOFExceptions.h"
+
+@interface EOAdaptorChannel(Internals)
+- (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs;
+@end /* EOAdaptorChannel(Internals) */
+
+@implementation EOAdaptorChannel
+
++ (NSCalendarDate*)dateForAttribute:(EOAttribute*)attr
+ year:(int)year month:(unsigned)month day:(unsigned)day
+ hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second
+ zone:(NSZone*)zone
+{
+ NSTimeZone *serverTimeZone = [attr serverTimeZone];
+ NSTimeZone *clientTimeZone = [attr clientTimeZone];
+ NSCalendarDate *date;
+ NSString *fmt;
+
+ if (serverTimeZone == nil) serverTimeZone = [NSTimeZone localTimeZone];
+ if (clientTimeZone == nil) clientTimeZone = [NSTimeZone localTimeZone];
+
+ date = AUTORELEASE([[NSCalendarDate allocWithZone:zone]
+ initWithYear:year month:month day:day hour:hour
+ minute:minute second:second timeZone:serverTimeZone]);
+ [date setTimeZone:clientTimeZone];
+ fmt = [attr calendarFormat];
+ [date setCalendarFormat:fmt ? fmt : [EOAttribute defaultCalendarFormat]];
+ return date;
+}
+
+- (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext {
+ ASSIGN(self->adaptorContext, _adaptorContext);
+
+ NS_DURING
+ [self->adaptorContext channelDidInit:self];
+ NS_HANDLER {
+ AUTORELEASE(self);
+ [localException raise];
+ }
+ NS_ENDHANDLER;
+
+ return self;
+}
+
+- (void)dealloc {
+ [self->adaptorContext channelWillDealloc:self];
+ RELEASE(self->adaptorContext);
+ [super dealloc];
+}
+
+/* open/close channel */
+
+- (BOOL)openChannel {
+ if(self->isOpen)
+ return NO;
+ self->isOpen = YES;
+
+ return YES;
+}
+
+- (void)closeChannel {
+ if ([self isFetchInProgress])
+ [self cancelFetch];
+ self->isOpen = NO;
+}
+
+/* modifications */
+
+- (Class)_adaptorExpressionClass {
+ return [[self->adaptorContext adaptor] expressionClass];
+}
+
+- (BOOL)_isNoRaiseOnModificationException:(NSException *)_exception {
+ /* for compatibility with non-X methods, translate some errors to a bool */
+ NSString *n;
+
+ n = [_exception name];
+ if ([n isEqualToString:@"EOEvaluationError"])
+ return YES;
+ if ([n isEqualToString:@"EODelegateRejects"])
+ return YES;
+
+ return NO;
+}
+
+- (NSException *)insertRowX:(NSDictionary *)row forEntity:(EOEntity *)entity {
+ EOSQLExpression *sqlexpr;
+ NSMutableDictionary *mrow = (id)row;
+ NSException *ex;
+
+ if (!isOpen)
+ return [[ChannelIsNotOpenedException new] autorelease];
+
+ if((row == nil) || (entity == nil)) {
+ return [NSException exceptionWithName:NSInvalidArgumentException
+ reason:@"row and entity arguments for "
+ @"insertRow:forEntity: must not be the nil object"
+ userInfo:nil];
+ }
+
+ if([self isFetchInProgress])
+ return [AdaptorIsFetchingException exceptionWithAdaptor:self];
+
+ if ([self->adaptorContext transactionNestingLevel] == 0)
+ return [NoTransactionInProgressException exceptionWithAdaptor:self];
+
+ if (delegateRespondsTo.willInsertRow) {
+ EODelegateResponse response;
+
+ mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]);
+ response = [delegate adaptorChannel:self
+ willInsertRow:mrow
+ forEntity:entity];
+ if (response == EODelegateRejects) {
+ return [NSException exceptionWithName:@"EODelegateRejects"
+ reason:@"delegate rejected insert"
+ userInfo:nil];
+ }
+ if (response == EODelegateOverrides)
+ return nil;
+ }
+
+ sqlexpr = [[[self->adaptorContext adaptor]
+ expressionClass]
+ insertExpressionForRow:mrow
+ entity:entity
+ channel:self];
+
+ ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
+ if (ex != nil)
+ return ex;
+
+ if(delegateRespondsTo.didInsertRow)
+ [delegate adaptorChannel:self didInsertRow:mrow forEntity:entity];
+
+ return nil;
+}
+
+- (NSException *)updateRowX:(NSDictionary *)row
+ describedByQualifier:(EOSQLQualifier *)qualifier
+{
+ EOSQLExpression *sqlexpr = nil;
+ NSMutableDictionary *mrow = (id)row;
+ NSException *ex;
+
+ if (!isOpen)
+ return [[ChannelIsNotOpenedException new] autorelease];
+
+ if (row == nil) {
+ return [NSException exceptionWithName:NSInvalidArgumentException
+ reason:
+ @"row argument for updateRow:describedByQualifier: "
+ @"must not be the nil object"
+ userInfo:nil];
+ }
+
+ if ([self isFetchInProgress])
+ return [AdaptorIsFetchingException exceptionWithAdaptor:self];
+
+ if ([self->adaptorContext transactionNestingLevel] == 0)
+ return [NoTransactionInProgressException exceptionWithAdaptor:self];
+
+ if (delegateRespondsTo.willUpdateRow) {
+ EODelegateResponse response;
+
+ mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]);
+ response = [delegate adaptorChannel:self
+ willUpdateRow:mrow
+ describedByQualifier:qualifier];
+ if (response == EODelegateRejects) {
+ return [NSException exceptionWithName:@"EODelegateRejects"
+ reason:@"delegate rejected update"
+ userInfo:nil];
+ }
+ if (response == EODelegateOverrides)
+ return nil;
+ }
+
+ sqlexpr = [[self _adaptorExpressionClass]
+ updateExpressionForRow:mrow
+ qualifier:qualifier
+ channel:self];
+
+ ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
+ if (ex != nil) return ex;
+
+ if (delegateRespondsTo.didUpdateRow) {
+ [delegate adaptorChannel:self
+ didUpdateRow:mrow
+ describedByQualifier:qualifier];
+ }
+ return nil;
+}
+
+- (NSException *)deleteRowsDescribedByQualifierX:(EOSQLQualifier *)qualifier {
+ EOSQLExpression *sqlexpr = nil;
+ NSException *ex;
+
+ if (!isOpen)
+ return [[ChannelIsNotOpenedException new] autorelease];
+
+ if ([self isFetchInProgress])
+ return [AdaptorIsFetchingException exceptionWithAdaptor:self];
+
+ if ([self->adaptorContext transactionNestingLevel] == 0)
+ return [NoTransactionInProgressException exceptionWithAdaptor:self];
+
+ if (delegateRespondsTo.willDeleteRows) {
+ EODelegateResponse response;
+
+ response = [delegate adaptorChannel:self
+ willDeleteRowsDescribedByQualifier:qualifier];
+ if (response == EODelegateRejects) {
+ return [NSException exceptionWithName:@"EODelegateRejects"
+ reason:@"delegate rejected delete"
+ userInfo:nil];
+ }
+ if (response == EODelegateOverrides)
+ return nil;
+ }
+
+ sqlexpr = [[self _adaptorExpressionClass]
+ deleteExpressionWithQualifier:qualifier
+ channel:self];
+
+ ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
+ if (ex != nil) return ex;
+
+ if (delegateRespondsTo.didDeleteRows)
+ [delegate adaptorChannel:self didDeleteRowsDescribedByQualifier:qualifier];
+
+ return nil;
+}
+
+/* compatibility methods (DEPRECATED, use the ...X methods */
+
+- (BOOL)insertRow:(NSDictionary *)_row forEntity:(EOEntity *)_entity {
+ NSException *ex;
+
+ ex = [self insertRowX:_row forEntity:_entity];
+ if (ex == nil)
+ return YES;
+ if ([self _isNoRaiseOnModificationException:ex])
+ return NO;
+ [ex raise];
+ return NO;
+}
+
+- (BOOL)updateRow:(NSDictionary *)_row
+ describedByQualifier:(EOSQLQualifier *)_q
+{
+ NSException *ex;
+
+ ex = [self updateRowX:_row describedByQualifier:_q];
+ if (ex == nil)
+ return YES;
+ if ([self _isNoRaiseOnModificationException:ex])
+ return NO;
+ [ex raise];
+ return NO;
+}
+
+- (BOOL)deleteRowsDescribedByQualifier:(EOSQLQualifier *)_qualifier {
+ NSException *ex;
+
+ ex = [self deleteRowsDescribedByQualifierX:_qualifier];
+ if (ex == nil)
+ return YES;
+ if ([self _isNoRaiseOnModificationException:ex])
+ return NO;
+ [ex raise];
+ return NO;
+}
+
+/* fetch operations */
+
+- (BOOL)selectAttributes:(NSArray *)attributes
+ describedByQualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ lock:(BOOL)lockFlag
+{
+ EOSQLExpression *sqlexpr = nil;
+ NSMutableArray *mattrs = (NSMutableArray *)attributes;
+ NSMutableArray *mfetch = (NSMutableArray *)fetchOrder;
+
+ if (!isOpen)
+ [[ChannelIsNotOpenedException new] raise];
+
+ if (attributes == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"attributes argument for selectAttributes:"
+ @"describedByQualifier:fetchOrder:lock: "
+ @"must not be the nil object"];
+ }
+
+ if ([self isFetchInProgress])
+ [[AdaptorIsFetchingException exceptionWithAdaptor:self] raise];
+
+ if ([self->adaptorContext transactionNestingLevel] == 0)
+ [[NoTransactionInProgressException exceptionWithAdaptor:self] raise];
+
+ if(delegateRespondsTo.willSelectAttributes) {
+ EODelegateResponse response;
+
+ mattrs = [[attributes mutableCopy] autorelease];
+ mfetch = [[fetchOrder mutableCopy] autorelease];
+
+ response = [delegate adaptorChannel:self
+ willSelectAttributes:mattrs
+ describedByQualifier:qualifier
+ fetchOrder:mfetch
+ lock:lockFlag];
+ if (response == EODelegateRejects)
+ return NO;
+ if (response == EODelegateOverrides)
+ return YES;
+ }
+
+#if 0
+#warning DEBUG LOG, REMOVE!
+ [self logWithFormat:@"fetch qualifier: %@", qualifier];
+#endif
+
+ sqlexpr = [[[self->adaptorContext adaptor]
+ expressionClass]
+ selectExpressionForAttributes:attributes
+ lock:lockFlag
+ qualifier:qualifier
+ fetchOrder:fetchOrder
+ channel:self];
+
+ if (![self evaluateExpression:[sqlexpr expressionValueForContext:nil]])
+ return NO;
+
+ if (delegateRespondsTo.didSelectAttributes) {
+ [delegate adaptorChannel:self
+ didSelectAttributes:mattrs
+ describedByQualifier:qualifier
+ fetchOrder:mfetch
+ lock:lockFlag];
+ }
+
+ return YES;
+}
+
+- (NSArray *)describeResults {
+ [self subclassResponsibility:_cmd];
+ return nil;
+}
+
+- (NSMutableDictionary *)fetchAttributes:(NSArray *)attributes
+ withZone:(NSZone *)_zone
+{
+ NSMutableDictionary *row = nil;
+
+ if (!self->isOpen)
+ [[ChannelIsNotOpenedException new] raise];
+
+ if (_zone == NULL)
+ _zone = NSDefaultMallocZone();
+
+ if(![self isFetchInProgress])
+ [[AdaptorIsNotFetchingException exceptionWithAdaptor:self] raise];
+
+ if(delegateRespondsTo.willFetchAttributes) {
+ row = [delegate adaptorChannel:self
+ willFetchAttributes:attributes
+ withZone:_zone];
+ }
+
+ /* NOTE: primaryFetchAttributes:withZone: have to set the isFetchInProgress
+ status */
+ if(row == nil)
+ row = [self primaryFetchAttributes:attributes withZone:_zone];
+
+ if(row) {
+ if(delegateRespondsTo.didFetchAttributes)
+ row = [delegate adaptorChannel:self
+ didFetchAttributes:row
+ withZone:_zone];
+ if(delegateRespondsTo.didChangeResultSet)
+ [delegate adaptorChannelDidChangeResultSet:self];
+ }
+ else {
+ /* Do not set here the isFetchInProgress status since only subclasses
+ can know whether there are more SELECT commands to be executed.
+ Setting the status here to NO will overwrite the adaptor subclass
+ intention. */
+ if(delegateRespondsTo.didFinishFetching)
+ [delegate adaptorChannelDidFinishFetching:self];
+ }
+ return row;
+}
+
+- (BOOL)isFetchInProgress {
+ return self->isFetchInProgress;
+}
+
+- (void)cancelFetch {
+ if (!isOpen)
+ [[ChannelIsNotOpenedException new] raise];
+
+ self->isFetchInProgress = NO;
+}
+
+- (NSMutableDictionary *)dictionaryWithObjects:(id *)objects
+ forAttributes:(NSArray *)attributes zone:(NSZone *)zone
+{
+ [self notImplemented:_cmd];
+ return nil;
+}
+
+- (NSMutableDictionary*)primaryFetchAttributes:(NSArray *)attributes
+ withZone:(NSZone *)zone
+{
+ [self subclassResponsibility:_cmd];
+ return nil;
+}
+
+- (BOOL)evaluateExpression:(NSString *)anExpression {
+ [self subclassResponsibility:_cmd];
+ return NO;
+}
+- (NSException *)evaluateExpressionX:(NSString *)_sql {
+ NSException *ex;
+ BOOL ok;
+
+ ex = nil;
+ ok = NO;
+ NS_DURING
+ ok = [self evaluateExpression:_sql];
+ NS_HANDLER
+ ex = [localException retain];
+ NS_ENDHANDLER;
+
+ if (ex) return [ex autorelease];
+ if (ok) return nil;
+
+ return [NSException exceptionWithName:@"EOEvaluationError"
+ reason:@"could not evaluate SQL expression"
+ userInfo:nil];
+}
+
+- (EOAdaptorContext *)adaptorContext {
+ return self->adaptorContext;
+}
+
+- (EOModel *)describeModelWithTableNames:(NSArray *)tableNames {
+ [self subclassResponsibility:_cmd];
+ return nil;
+}
+
+- (NSArray *)describeTableNames {
+ [self subclassResponsibility:_cmd];
+ return nil;
+}
+
+- (BOOL)readTypesForEntity:(EOEntity*)anEntity {
+ [self subclassResponsibility:_cmd];
+ return NO;
+}
+
+- (BOOL)readTypeForAttribute:(EOAttribute*)anAttribute {
+ [self subclassResponsibility:_cmd];
+ return NO;
+}
+
+// delegate
+
+- (id)delegate {
+ return self->delegate;
+}
+
+- (void)setDelegate:(id)_delegate {
+ self->delegate = _delegate;
+
+ delegateRespondsTo.willInsertRow =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:willInsertRow:forEntity:)];
+ delegateRespondsTo.didInsertRow =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:didInsertRow:forEntity:)];
+ delegateRespondsTo.willUpdateRow =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:willUpdateRow:describedByQualifier:)];
+ delegateRespondsTo.didUpdateRow =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:didUpdateRow:describedByQualifier:)];
+ delegateRespondsTo.willDeleteRows =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:willDeleteRowsDescribedByQualifier:)];
+ delegateRespondsTo.didDeleteRows =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:didDeleteRowsDescribedByQualifier:)];
+ delegateRespondsTo.willSelectAttributes =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:willSelectAttributes:
+ describedByQualifier:fetchOrder:lock:)];
+ delegateRespondsTo.didSelectAttributes =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:didSelectAttributes:
+ describedByQualifier:fetchOrder:lock:)];
+ delegateRespondsTo.willFetchAttributes =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:willFetchAttributes:withZone:)];
+ delegateRespondsTo.didFetchAttributes =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:didFetchAttributes:withZone:)];
+ delegateRespondsTo.didChangeResultSet =
+ [delegate respondsToSelector:
+ @selector(adaptorChannelDidChangeResultSet:)];
+ delegateRespondsTo.didFinishFetching =
+ [delegate respondsToSelector:
+ @selector(adaptorChannelDidFinishFetching:)];
+ delegateRespondsTo.willEvaluateExpression =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:willEvaluateExpression:)];
+ delegateRespondsTo.didEvaluateExpression =
+ [delegate respondsToSelector:
+ @selector(adaptorChannel:didEvaluateExpression:)];
+}
+
+- (void)setDebugEnabled:(BOOL)flag {
+ self->debugEnabled = flag;
+}
+
+- (BOOL)isDebugEnabled {
+ return self->debugEnabled;
+}
+- (BOOL)isOpen {
+ return self->isOpen;
+}
+
+@end /* EOAdaptorChannel */
+
+#import <EOControl/EOFetchSpecification.h>
+
+@implementation EOAdaptorChannel(PrimaryKeyGeneration) // new in EOF2
+
+- (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity {
+ return nil;
+}
+
+@end /* EOAdaptorChannel(PrimaryKeyGeneration) */
+
+@implementation EOAdaptorChannel(EOF2Additions)
+
+- (void)selectAttributes:(NSArray *)_attributes
+ fetchSpecification:(EOFetchSpecification *)_fspec
+ lock:(BOOL)_flag
+ entity:(EOEntity *)_entity
+{
+ EOSQLQualifier *q;
+ BOOL isOk;
+
+ q = (EOSQLQualifier *)[_fspec qualifier];
+
+ isOk = [self selectAttributes:_attributes
+ describedByQualifier:q
+ fetchOrder:[_fspec sortOrderings]
+ lock:_flag];
+ if (!isOk) {
+ [NSException raise:@"Select failed"
+ format:@"could not select attributes for fetch spec"];
+ }
+}
+
+- (void)setAttributesToFetch:(NSArray *)_attributes {
+ [self notImplemented:_cmd];
+}
+- (NSArray *)attributesToFetch {
+ NSLog(@"ERROR(%s): subclasses must override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+- (NSMutableDictionary *)fetchRowWithZone:(NSZone *)_zone {
+ return [self fetchAttributes:[self attributesToFetch] withZone:_zone];
+}
+
+@end /* EOAdaptorChannel(EOF2Additions) */
+
+@implementation EOAdaptorChannel(Internals)
+
+- (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs {
+ return _attrs;
+}
+
+@end /* EOAdaptorChannel(Internals) */
--- /dev/null
+/*
+ EOAdaptorContext.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import <Foundation/NSUtilities.h>
+#import <Foundation/NSValue.h>
+#import <Foundation/NSArray.h>
+
+#import "common.h"
+#import "EOAdaptor.h"
+#import "EOAdaptorContext.h"
+#import "EOAdaptorChannel.h"
+
+@implementation EOAdaptorContext
+
+- (id)initWithAdaptor :(EOAdaptor*)_adaptor
+{
+ ASSIGN(self->adaptor, _adaptor);
+ self->channels = [[NSMutableArray alloc] initWithCapacity:2];
+ [self->adaptor contextDidInit:self];
+ return self;
+}
+
+- (void)dealloc
+{
+ [self->adaptor contextWillDealloc:self];
+ RELEASE(self->adaptor);
+ RELEASE(self->channels);
+ [super dealloc];
+}
+
+- (EOAdaptorChannel*)createAdaptorChannel
+{
+ return AUTORELEASE([[[adaptor adaptorChannelClass] alloc]
+ initWithAdaptorContext:self]);
+}
+- (NSArray *)channels
+{
+ NSMutableArray *ma;
+ unsigned i, count;
+
+ if ((count = [self->channels count]) == 0)
+ return nil;
+
+ ma = [NSMutableArray arrayWithCapacity:count];
+ for (i = 0; i < count; i++)
+ [ma addObject:[[self->channels objectAtIndex:i] nonretainedObjectValue]];
+
+ return ma;
+}
+
+- (void)channelDidInit:aChannel
+{
+ [self->channels addObject:[NSValue valueWithNonretainedObject:aChannel]];
+}
+
+- (void)channelWillDealloc:(id)aChannel
+{
+ int i;
+
+ for (i = [self->channels count] - 1; i >= 0; i--)
+ if ([[channels objectAtIndex:i] nonretainedObjectValue] == aChannel) {
+ [channels removeObjectAtIndex:i];
+ break;
+ }
+}
+
+- (BOOL)hasOpenChannels
+{
+ int i, count = [channels count];
+
+ for (i = 0; i < count; i++)
+ if ([[[channels objectAtIndex:i] nonretainedObjectValue] isOpen])
+ return YES;
+
+ return NO;
+}
+
+- (BOOL)hasBusyChannels
+{
+ int i, count = [channels count];
+
+ for (i = 0; i < count; i++)
+ if ([[[channels objectAtIndex:i] nonretainedObjectValue]
+ isFetchInProgress])
+ return YES;
+
+ return NO;
+}
+
+- (BOOL)beginTransaction
+{
+ if (transactionNestingLevel && ![self canNestTransactions])
+ return NO;
+
+ if ([self->channels count] == 0)
+ return NO;
+
+ if(delegateRespondsTo.willBegin) {
+ EODelegateResponse response = [delegate adaptorContextWillBegin:self];
+ if(response == EODelegateRejects)
+ return NO;
+ else if(response == EODelegateOverrides)
+ return YES;
+ }
+ if([self primaryBeginTransaction] == NO)
+ return NO;
+
+ [self transactionDidBegin];
+
+ if(delegateRespondsTo.didBegin)
+ [delegate adaptorContextDidBegin:self];
+ return YES;
+}
+
+- (BOOL)commitTransaction
+{
+ if(!transactionNestingLevel || [self hasBusyChannels])
+ return NO;
+
+ if (![channels count])
+ return NO;
+
+ if(delegateRespondsTo.willCommit) {
+ EODelegateResponse response = [delegate adaptorContextWillCommit:self];
+ if(response == EODelegateRejects)
+ return NO;
+ else if(response == EODelegateOverrides)
+ return YES;
+ }
+
+ if([self primaryCommitTransaction] == NO)
+ return NO;
+
+ [self transactionDidCommit];
+
+ if(delegateRespondsTo.didCommit)
+ [delegate adaptorContextDidCommit:self];
+ return YES;
+}
+
+- (BOOL)rollbackTransaction
+{
+ if(!transactionNestingLevel || [self hasBusyChannels])
+ return NO;
+
+ if (![channels count])
+ return NO;
+
+ if(delegateRespondsTo.willRollback) {
+ EODelegateResponse response
+ = [delegate adaptorContextWillRollback:self];
+ if(response == EODelegateRejects)
+ return NO;
+ else if(response == EODelegateOverrides)
+ return YES;
+ }
+
+ if([self primaryRollbackTransaction] == NO)
+ return NO;
+
+ [self transactionDidRollback];
+
+ if(delegateRespondsTo.didRollback)
+ [delegate adaptorContextDidRollback:self];
+ return YES;
+}
+
+- (void)transactionDidBegin
+{
+ /* Increment the transaction scope */
+ transactionNestingLevel++;
+}
+
+- (void)transactionDidCommit
+{
+ /* Decrement the transaction scope */
+ transactionNestingLevel--;
+}
+
+- (void)transactionDidRollback
+{
+ /* Decrement the transaction scope */
+ transactionNestingLevel--;
+}
+
+- (void)setDelegate:(id)_delegate {
+ self->delegate = _delegate;
+
+ delegateRespondsTo.willBegin =
+ [delegate respondsToSelector:@selector(adaptorContextWillBegin:)];
+ delegateRespondsTo.didBegin =
+ [delegate respondsToSelector:@selector(adaptorContextDidBegin:)];
+ delegateRespondsTo.willCommit =
+ [delegate respondsToSelector:@selector(adaptorContextWillCommit:)];
+ delegateRespondsTo.didCommit =
+ [delegate respondsToSelector:@selector(adaptorContextDidCommit:)];
+ delegateRespondsTo.willRollback =
+ [delegate respondsToSelector:@selector(adaptorContextWillRollback:)];
+ delegateRespondsTo.didRollback =
+ [delegate respondsToSelector:@selector(adaptorContextDidRollback:)];
+}
+- (id)delegate {
+ return self->delegate;
+}
+
+- (EOAdaptor *)adaptor {
+ return self->adaptor;
+}
+- (BOOL)canNestTransactions {
+ /* deprecated in WO 4.5 */
+ return NO;
+}
+- (unsigned)transactionNestingLevel {
+ /* deprecated in WO 4.5 */
+ return self->transactionNestingLevel;
+}
+- (BOOL)hasOpenTransaction {
+ /* new in WO 4.5 */
+ return self->transactionNestingLevel > 0 ? YES : NO;
+}
+
+- (BOOL)primaryBeginTransaction {
+ return NO;
+}
+
+- (BOOL)primaryCommitTransaction {
+ return NO;
+}
+
+- (BOOL)primaryRollbackTransaction {
+ return NO;
+}
+
+@end /* EOAdaptorContext */
--- /dev/null
+/*
+ EOAdaptorDataSource.m
+
+ Copyright (C) SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+ Date: 1999-2004
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAdaptorDataSource.m 1 2004-08-20 10:38:46Z znek $
+
+/*
+ column-names must have small letterso
+ hints:
+ EOPrimaryKeyAttributeNamesHint - name of primary key attributes
+ EOPrimaryKeyAttributesHint - primary key attributes
+ EOFetchResultTimeZone - NSTimeZone object for dates
+*/
+
+#define EOAdaptorDataSource_DEBUG 0
+
+#include <NGExtensions/NGExtensions.h>
+#include <GDLAccess/GDLAccess.h>
+#include <EOControl/EOControl.h>
+#include "common.h"
+
+NSString *EOPrimaryKeyAttributeNamesHint = @"EOPrimaryKeyAttributeNamesHint";
+NSString *EOPrimaryKeyAttributesHint = @"EOPrimaryKeyAttributesHint";
+NSString *EOFetchResultTimeZone = @"EOFetchResultTimeZoneHint";
+
+@interface NSObject(Private)
+- (NSString *)newKeyExpression;
+- (NSArray *)_primaryKeyAttributesForTableName:(NSString *)_entityName
+ channel:(EOAdaptorChannel *)_adChannel;
+- (NSArray *)_primaryKeyAttributeNamesForTableName:(NSString *)_entityName
+ channel:(EOAdaptorChannel *)_adChannel;
+@end
+
+static EONull *null = nil;
+
+@interface EOAdaptorChannel(Internals)
+- (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs;
+@end /* EOAdaptorChannel(Internals) */
+
+@interface EOQualifier(SqlExpression)
+- (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor
+ attributes:(NSArray *)_attrs;
+@end /* EOQualifier(SqlExpression) */
+
+@interface EOAdaptorDataSource(Private)
+- (NSMutableString *)_selectListWithChannel:(EOAdaptorChannel *)_adChan;
+- (NSString *)_whereExprWithChannel:(EOAdaptorChannel *)_adChan;
+- (NSString *)_whereClauseForGlobaID:(EOKeyGlobalID *)_gid
+ adaptor:(EOAdaptor *)_adaptor channel:(EOAdaptorChannel *)_adChan;
+- (NSDictionary *)_mapAttrsWithValues:(NSDictionary *)_keyValues
+ tableName:(NSString *)_tableName channel:(EOAdaptorChannel *)_adChan;
+@end /* EOAdaptorDataSource(Private) */
+
+@interface EOAdaptorDataSource(Internals)
+- (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel
+ connectionDictionary:(NSDictionary *)_connDict;
+@end /* EOAdaptorDataSource(Internals) */
+
+@interface EODataSource(Notificiations)
+- (void)postDataSourceChangedNotification;
+@end
+
+@implementation EOAdaptorDataSource
+
+static NSNotificationCenter *nc = nil;
+
+static NSNotificationCenter *getNC(void ) {
+ if (nc == nil)
+ nc = [[NSNotificationCenter defaultCenter] retain];
+ return nc;
+}
+
++ (void)initialize {
+ NSAssert2([super version] == 1,
+ @"invalid superclass (%@) version %i !",
+ NSStringFromClass([self superclass]), [super version]);
+ if (null == nil)
+ null = [[EONull null] retain];
+}
++ (int)version {
+ return [super version] + 1; /* v2 */
+}
+
+- (id)initWithAdaptorName:(NSString *)_adName
+ connectionDictionary:(NSDictionary *)_dict
+ primaryKeyGenerationDictionary:(NSDictionary *)_pkGen
+{
+ EOAdaptor *ad = nil;
+ EOAdaptorContext *ctx = nil;
+ EOAdaptorChannel *adc = nil;
+
+ ad = [EOAdaptor adaptorWithName:_adName];
+ [ad setConnectionDictionary:_dict];
+ [ad setPkeyGeneratorDictionary:_pkGen];
+ ctx = [ad createAdaptorContext];
+ adc = [ctx createAdaptorChannel];
+
+ return [self initWithAdaptorChannel:adc connectionDictionary:_dict];
+}
+
+- (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel {
+ return [self initWithAdaptorChannel:_channel connectionDictionary:nil];
+}
+
+- (id)initWithAdaptorChannel:(EOAdaptorChannel *)_channel
+ connectionDictionary:(NSDictionary *)_connDict
+{
+ if ((self = [super init])) {
+ self->adChannel = [_channel retain];
+ self->connectionDictionary = [_connDict copy];
+ self->commitTransaction = NO;
+
+ [getNC()
+ addObserver:self selector:@selector(_adDataSourceChanged:)
+ name:@"EOAdaptorDataSourceChanged" object:nil];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [getNC() removeObserver:self];
+ [self->fetchSpecification release];
+ [self->connectionDictionary release];
+ [self->adChannel release];
+ [self->__attributes release];
+ [self->__qualifier release];
+ [super dealloc];
+}
+
+/* notifications */
+
+- (void)postDataSourceItselfChangedNotification {
+ [super postDataSourceChangedNotification];
+}
+
+- (void)postDataSourceChangedNotification {
+ [getNC() postNotificationName:@"EOAdaptorDataSourceChanged" object:self];
+ [self postDataSourceItselfChangedNotification];
+}
+
+- (void)_adDataSourceChanged:(NSNotification *)_notification {
+ EOAdaptorDataSource *ads;
+
+ if ((ads = [_notification object]) == self)
+ return;
+ if (ads == nil)
+ return;
+
+ [self postDataSourceItselfChangedNotification];
+
+#if 0
+ if (![ads->connectionDictionary isEqual:self->connectionDictionary])
+ /* different database ... */
+ return;
+
+ if ((ads->fetchSpecification == nil) || (self->fetchSpecification == nil)) {
+ [self postDataSourceChangedNotification];
+ return;
+ }
+
+ /* check fspecs for entity ... */
+ if ([[ads->fetchSpecification entityName]
+ isEqualToString:
+ [self->fetchSpecification entityName]]) {
+ [self postDataSourceChangedNotification];
+ return;
+ }
+#endif
+}
+
+/* fetching */
+
+- (EOAdaptorChannel *)beginTransaction {
+ EOAdaptorContext *ctx = nil;
+
+ [self openChannel];
+ ctx = [self->adChannel adaptorContext];
+ if ([ctx hasOpenTransaction] == NO) {
+ [ctx beginTransaction];
+ self->commitTransaction = YES;
+ }
+ return self->adChannel;
+}
+
+- (void)commitTransaction {
+ if (self->commitTransaction) {
+ [[self->adChannel adaptorContext] commitTransaction];
+ // [self->adChannel closeChannel];
+ self->commitTransaction = NO;
+ }
+}
+
+- (void)rollbackTransaction {
+ [[self->adChannel adaptorContext] rollbackTransaction];
+ // [self->adChannel closeChannel];
+ self->commitTransaction = NO;
+}
+
+- (void)openChannel {
+ if (![self->adChannel isOpen]) {
+ [self->adChannel openChannel];
+ }
+}
+
+- (void)closeChannel {
+ if (![self->adChannel isOpen])
+ return;
+
+ if ([[self->adChannel adaptorContext] transactionNestingLevel]) {
+ NSLog(@"%s was called while transaction in progress, rollback will called",
+ __PRETTY_FUNCTION__);
+ [self rollbackTransaction];
+ }
+ [self->adChannel closeChannel];
+}
+
+- (NSArray *)fetchObjects {
+ /* TODO: split up this HUGE method! */
+ NSString *entityName = nil;
+ NSString *whereExpr = nil;
+ NSMutableString *orderByExpr = nil;
+ NSMutableString *selectList = nil;
+ NSMutableString *expression = nil;
+ NSMutableArray *result = nil;
+ NSArray *attrs = nil;
+ EOAdaptor *adaptor = nil;
+ NSArray *pKeys = nil;
+ EOQualifier *qual = nil;
+ EOAdaptorChannel *adChan = nil;
+ int pKeyCnt = 0;
+ NSTimeZone *tz = nil;
+ BOOL localComTrans;
+
+ if (self->fetchSpecification == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"fetchSpecification required for table name"];
+ return nil;
+ }
+
+ entityName = [self->fetchSpecification entityName];
+
+ if (entityName == nil || [entityName length] == 0) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"missing entity name"];
+ }
+ localComTrans = [[self->adChannel adaptorContext] hasOpenTransaction]
+ ? NO : YES;
+
+ adChan = [self beginTransaction];
+ pKeys = [self _primaryKeyAttributeNamesForTableName:entityName
+ channel:adChan];
+
+ if ((pKeyCnt = [pKeys count]) == 0) {
+ NSLog(@"ERROR[%s]: missing primary keys for table %@",
+ __PRETTY_FUNCTION__, entityName);
+ return nil;
+ }
+ qual = [self->fetchSpecification qualifier];
+
+ if (qual == nil)
+ qual = [EOQualifier qualifierWithQualifierFormat:@"1=1"];
+
+ ASSIGN(self->__qualifier, qual);
+
+ attrs = [adChan attributesForTableName:entityName];
+
+ if (attrs == nil) {
+ RELEASE(self->__qualifier); self->__qualifier = nil;
+
+ NSLog(@"ERROR[%s]: could not find table '%@' in database.",
+ __PRETTY_FUNCTION__, entityName);
+ [self rollbackTransaction];
+ return nil;
+ }
+ if ([attrs count] == 0) {
+ RELEASE(self->__qualifier); self->__qualifier = nil;
+
+ NSLog(@"ERROR[%s]: missing columns in table '%@'.",
+ __PRETTY_FUNCTION__, entityName);
+ [self rollbackTransaction];
+ return nil;
+ }
+ tz = [[self->fetchSpecification hints] objectForKey:EOFetchResultTimeZone];
+
+ ASSIGN(self->__attributes, attrs);
+ adaptor = [[adChan adaptorContext] adaptor];
+ {
+ NSArray *a;
+ NSSet *tableKeys = nil;
+ NSSet *qualifierKeys = nil;
+
+ a = [[[qual allQualifierKeys] allObjects] map:@selector(lowercaseString)];
+ qualifierKeys = [[NSSet alloc] initWithArray:a];
+ a = [[attrs map:@selector(columnName)] map:@selector(lowercaseString)];
+ tableKeys = [[NSSet alloc] initWithArray:a];
+
+ if ([qualifierKeys isSubsetOfSet:tableKeys] == NO) {
+ NSString *format = nil;
+
+ format = [NSString stringWithFormat:
+ @"EOAdaptorDataSource: using unmapped key in "
+ @"qualifier tableKeys <%@> qualifierKeys <%@> "
+ @"qualifier <%@>",
+ tableKeys, qualifierKeys, qual];
+
+ RELEASE(self->__attributes); self->__attributes = nil;
+ RELEASE(self->__qualifier); self->__qualifier = nil;
+ RELEASE(tableKeys); tableKeys = nil;
+ [self rollbackTransaction];
+ [[[InvalidQualifierException alloc] initWithFormat:format] raise];
+ }
+ RELEASE(tableKeys); tableKeys = nil;
+ RELEASE(qualifierKeys); qualifierKeys = nil;
+ }
+
+ whereExpr = [self _whereExprWithChannel:adChan];
+ selectList = [self _selectListWithChannel:adChan];
+ { /* order by expr */
+ NSEnumerator *enumerator = nil;
+ EOSortOrdering *sortOrdering = nil;
+ int orderCnt = 0;
+
+ enumerator = [[self->fetchSpecification sortOrderings] objectEnumerator];
+
+ while ((sortOrdering = [enumerator nextObject])) {
+ SEL selector = NULL;
+ NSString *key = nil;
+ EOAttribute *keyAttr = nil;
+ int order = 0; /* 0 - not used; 1 - asc; 2 - desc */
+ BOOL inSensitive = NO;
+ NSString *orderTmp = nil;
+
+ if (orderByExpr == nil) {
+ orderByExpr = [NSMutableString stringWithCapacity:64];
+ }
+ else {
+ [orderByExpr appendString:@", "];
+ }
+ if ((selector = [sortOrdering selector])) {
+ if (SEL_EQ(selector, EOCompareAscending)) {
+ order = 1;
+ }
+ else if (SEL_EQ(selector, EOCompareDescending)) {
+ order = 2;
+ }
+ else if (SEL_EQ(selector, EOCompareCaseInsensitiveAscending)) {
+ order = 1;
+ inSensitive = YES;
+ }
+ else if (SEL_EQ(selector, EOCompareCaseInsensitiveDescending)) {
+ inSensitive = YES;
+ order = 2;
+ }
+ }
+ key = [sortOrdering key];
+
+ if (key == nil || [key length] == 0) {
+ NSLog(@"WARNING[%s]: wrong key in sortordering %@",
+ __PRETTY_FUNCTION__, key);
+ continue;
+ }
+ {
+ NSEnumerator *en = nil;
+ id obj = nil;
+
+ key = [key lowercaseString];
+ en = [attrs objectEnumerator];
+ while ((obj = [en nextObject])) {
+ if ([[[(EOAttribute *)obj columnName] lowercaseString]
+ isEqualToString:key])
+ break;
+ }
+ if (obj == nil) {
+ RELEASE(self->__attributes); self->__attributes = nil;
+ RELEASE(self->__qualifier); self->__qualifier = nil;
+ RELEASE(expression); expression = nil;
+ [self rollbackTransaction];
+ [[[InvalidAttributeException alloc]
+ initWithFormat:@"couldn`t find EOAttribute for SortOrdering"
+ @" %@ Attributes %@",
+ sortOrdering, attrs] raise];
+ }
+ keyAttr = obj;
+ }
+ key = [adaptor formatAttribute:keyAttr];
+ orderTmp = [NSString stringWithFormat:@"order_by_expr_%d", orderCnt++];
+ [orderByExpr appendString:orderTmp];
+ if (order == 1) {
+ [orderByExpr appendString:@" ASC"];
+ }
+ else if (order == 2) {
+ [orderByExpr appendString:@" DESC"];
+ }
+ { /* manipulate select expr */
+ if (inSensitive) {
+ if ([[keyAttr valueClassName] isEqualToString:@"NSString"]) {
+ key = [NSString stringWithFormat:@"LOWER(%@)", key];
+ }
+ else
+ NSLog(@"WARNING[%s]: inSensitive expression for no text attribute",
+ __PRETTY_FUNCTION__);
+ }
+ {
+ NSString *str = nil;
+
+ str = [key stringByAppendingString:@" "];
+ str = [str stringByAppendingString:orderTmp];
+ str = [str stringByAppendingString:@", "];
+
+ [selectList insertString:str atIndex:0];
+ }
+ }
+ }
+ }
+ expression = [[NSMutableString alloc] initWithCapacity:256];
+ [expression appendString:@"SELECT "];
+
+ if ([self->fetchSpecification usesDistinct])
+ [expression appendString:@"DISTINCT "];
+
+ [expression appendString:selectList];
+ [expression appendString:@" FROM "];
+ [expression appendString:entityName];
+ if ([whereExpr length] > 0) {
+ [expression appendString:@" WHERE "];
+ [expression appendString:whereExpr];
+ }
+ if (orderByExpr != nil && [orderByExpr length] > 0) {
+ [expression appendString:@" ORDER BY "];
+ [expression appendString:orderByExpr];
+ }
+
+ if (![adChan evaluateExpression:expression]) {
+ RELEASE(self->__attributes); self->__attributes = nil;
+ RELEASE(self->__qualifier); self->__qualifier = nil;
+ AUTORELEASE(expression);
+ [adChan cancelFetch];
+ [self rollbackTransaction];
+ [[[EOAdaptorException alloc]
+ initWithFormat:@"evaluateExpression of %@ failed", expression] raise];
+ }
+ result = [NSMutableArray arrayWithCapacity:64];
+ {
+ NSMutableDictionary *row = nil;
+ unsigned fetchCnt = 0;
+ unsigned fetchLimit = 0;
+ unsigned attrCnt = 0;
+ id *values = NULL;
+ id *keys = NULL;
+
+ attrCnt = [attrs count];
+ values = calloc(attrCnt + 2, sizeof(id));
+ keys = calloc(attrCnt + 2, sizeof(id));
+ fetchLimit = [self->fetchSpecification fetchLimit];
+
+ while ((row = [adChan fetchAttributes:attrs withZone:NULL])) {
+ NSEnumerator *enumerator = nil;
+ id attr = nil;
+ int rowCnt = 0;
+ NSDictionary *r = nil;
+ id *pKeyVs = NULL;
+ int pKeyVCnt = 0;
+
+ pKeyVs = calloc(pKeyCnt, sizeof(id));
+ enumerator = [attrs objectEnumerator];
+
+ while ((attr = [enumerator nextObject])) {
+ id obj;
+ NSString *cn;
+
+
+ obj = [row objectForKey:[(EOAttribute *)attr name]];
+
+ if (obj == nil)
+ continue;
+
+ if (tz) {
+ static Class NSCalendarDateClass = nil;
+
+ if (NSCalendarDateClass == nil)
+ NSCalendarDateClass = [NSCalendarDate class];
+
+ if ([obj isKindOfClass:NSCalendarDateClass]) {
+ [obj setTimeZone:tz];
+ }
+ }
+ cn = [[attr columnName] lowercaseString];
+ values[rowCnt] = obj;
+ keys[rowCnt] = cn;
+ rowCnt++;
+
+ if ([pKeys containsObject:cn]) {
+ int idx;
+
+ idx = [pKeys indexOfObject:cn];
+ NSAssert4(idx <= (pKeyCnt - 1) && pKeyVs[idx] == nil,
+ @"internal inconsistency in EOAdaptorDataSource "
+ @"while fetch idx[%d] > (pKeyCnt - 1)[%d] "
+ @"pKeyVs[idx] (%@[%d]);", idx, (pKeyCnt - 1),
+ pKeyVs[idx], idx);
+
+ pKeyVs[idx] = obj;
+ pKeyVCnt++;
+ }
+ }
+ if (pKeyCnt != pKeyVCnt)
+ NSAssert(NO, @"internal inconsistency in EOAdaptorDataSource "
+ @"while fetch");
+
+ {
+ EOGlobalID *gid;
+
+ gid = [EOKeyGlobalID globalIDWithEntityName:entityName
+ keys:pKeyVs keyCount:pKeyVCnt zone:NULL];
+
+ if (self->connectionDictionary) {
+ gid = [[EOAdaptorGlobalID alloc] initWithGlobalID:gid
+ connectionDictionary:
+ self->connectionDictionary];
+ AUTORELEASE(gid);
+ }
+ values[rowCnt] = gid;
+ keys[rowCnt] = @"globalID";
+ rowCnt++;
+ }
+ fetchCnt++;
+ r = [[NSMutableDictionary alloc]
+ initWithObjects:values forKeys:keys count:rowCnt];
+ [result addObject:r];
+ RELEASE(r); r = nil;
+ free(pKeyVs); pKeyVs = NULL;
+ if (fetchLimit == fetchCnt) {
+ break;
+ }
+ }
+ free(values); values = NULL;
+ free(keys); keys = NULL;
+ }
+ [adChan cancelFetch];
+ if (localComTrans)
+ [self commitTransaction];
+
+ RELEASE(expression); expression = nil;
+ RELEASE(self->__qualifier); self->__qualifier = nil;
+ RELEASE(self->__attributes); self->__attributes = nil;
+ return result;
+}
+
+- (id)createObject {
+ return [NSMutableDictionary dictionary];
+}
+
+- (void)insertObject:(id)_obj {
+ NSString *key = nil;
+ NSString *tableName = nil;
+ NSMutableString *expression = nil;
+ EOAdaptor *adaptor = nil;
+ NSArray *pKeys = nil;
+ id obj = nil;
+ EOAdaptorChannel *adChan = nil;
+
+ int oVCnt = 0;
+ NSString **objectKeyAttrValue = NULL;
+
+ NSEnumerator *enumerator = nil;
+ id pKey = nil;
+
+ BOOL localComTrans;
+
+ if ([[self->adChannel adaptorContext] hasOpenTransaction])
+ localComTrans = NO;
+ else
+ localComTrans = YES;
+
+ adChan = [self beginTransaction];
+ adaptor = [[adChan adaptorContext] adaptor];
+
+ if ((tableName = [self->fetchSpecification entityName]) == nil) {
+ [self rollbackTransaction];
+ [NSException raise:NSInvalidArgumentException
+ format:@"couldn`t insert obj %@ missing entityName in "
+ @"fetchSpecification", _obj];
+ }
+
+ /* create or apply primary keys */
+#if EOAdaptorDataSource_DEBUG
+ NSLog(@"insert obj %@", _obj);
+#endif
+
+ pKeys = [self _primaryKeyAttributeNamesForTableName:tableName channel:adChan];
+
+#if EOAdaptorDataSource_DEBUG
+ NSLog(@"got primary keys %@", pKeys);
+#endif
+
+ objectKeyAttrValue = calloc([pKeys count], sizeof(id));
+ enumerator = [pKeys objectEnumerator];
+
+ while ((pKey = [enumerator nextObject])) {
+ id pKeyObj;
+
+ pKeyObj = [_obj valueForKey:pKey];
+
+#if EOAdaptorDataSource_DEBUG
+ NSLog(@"pk in obj %@:<%@> ", pKey, pKeyObj);
+#endif
+
+ if (![pKeyObj isNotNull]) {
+ /* try to build primary key */
+ NSString *newKeyExpr = nil;
+ NSDictionary *row = nil;
+
+#if EOAdaptorDataSource_DEBUG
+ NSLog(@"pKeyObj !isNotNull");
+#endif
+
+ if ([pKeys count] != 1) {
+ [self rollbackTransaction];
+ [NSException raise:NSInternalInconsistencyException
+ format:@"more than one primary key, "
+ @"and primary key for %@ is not set", pKey];
+ }
+ if (![adaptor respondsToSelector:@selector(newKeyExpression)]) {
+ [self rollbackTransaction];
+ [NSException raise:NSInternalInconsistencyException
+ format:@"got no newkey expression, insert failed"];
+ }
+ newKeyExpr = [(id)adaptor newKeyExpression];
+ if (newKeyExpr == nil) {
+ [self rollbackTransaction];
+ [NSException raise:NSInternalInconsistencyException
+ format:@"missing newKeyExpression for adaptor[%@] %@...",
+ NSStringFromClass([adaptor class]), adaptor];
+ }
+ if (![adChan evaluateExpression:newKeyExpr]) {
+ [adChan cancelFetch];
+ [self rollbackTransaction];
+ [[[EOAdaptorException alloc]
+ initWithFormat:@"couldn`t evaluate new key expression %@",
+ newKeyExpr] raise];
+ }
+ row = [adChan fetchAttributes:[adChan describeResults]
+ withZone:NULL];
+ [adChan cancelFetch];
+ if ((key = [[row objectEnumerator] nextObject]) == nil) {
+ [self rollbackTransaction];
+ [[[EOAdaptorException alloc]
+ initWithFormat:@"couldn`t fetch primary key"] raise];;
+ }
+ objectKeyAttrValue[oVCnt++] = key;
+ [_obj takeValue:key forKey:pKey];
+#if EOAdaptorDataSource_DEBUG
+ NSLog(@"_obj %@ after takeValue:%@ forKey:%@", _obj, key, pKey);
+#endif
+ }
+ else {
+ objectKeyAttrValue[oVCnt++] = pKeyObj;
+#if EOAdaptorDataSource_DEBUG
+ NSLog(@"objectKeyAttrValue takeValue %@ for idx %d", pKeyObj, oVCnt);
+#endif
+ }
+ }
+
+ /* construct SQL INSERT expression .. */
+
+ expression = [[NSMutableString alloc] initWithCapacity:256];
+ [expression appendString:@"INSERT INTO "];
+ [expression appendString:tableName];
+ [expression appendString:@"("];
+ {
+ NSDictionary *objects = nil;
+ NSEnumerator *enumerator = nil;
+ NSArray *allKeys = nil;
+ BOOL isFirst = YES;
+
+ objects = [self _mapAttrsWithValues:_obj
+ tableName:tableName
+ channel:adChan];
+ allKeys = [objects allKeys];
+ enumerator = [allKeys objectEnumerator];
+ while ((obj = [enumerator nextObject])) {
+ if (isFirst)
+ isFirst = NO;
+ else
+ [expression appendString:@", "];
+ [expression appendString:[adaptor formatAttribute:obj]];
+ }
+ [expression appendString:@") VALUES ("];
+ enumerator = [allKeys objectEnumerator];
+ isFirst = YES;
+ while ((obj = [enumerator nextObject])) {
+ id value;
+
+ if (isFirst)
+ isFirst = NO;
+ else
+ [expression appendString:@", "];
+ value = [objects objectForKey:obj];
+ if (value == nil) value = null;
+ [expression appendString:[adaptor formatValue:value forAttribute:obj]];
+ }
+ }
+ [expression appendString:@")"];
+
+ /* execute insert in SQL server .. */
+
+ if (![adChan evaluateExpression:expression]) {
+ [adChan cancelFetch];
+ enumerator = [pKeys objectEnumerator];
+ while ((pKey = [enumerator nextObject])) {
+ [_obj takeValue:[EONull null] forKey:pKey];
+ }
+ [self rollbackTransaction];
+ AUTORELEASE(expression);
+ [[[EOAdaptorException alloc]
+ initWithFormat:@"evaluateExpression %@ failed", expression] raise];
+ }
+ [adChan cancelFetch];
+ if (localComTrans)
+ [self commitTransaction];
+
+ /* construct new global id for record */
+
+ {
+ EOGlobalID *gid;
+
+ gid = [EOKeyGlobalID globalIDWithEntityName:tableName
+ keys:objectKeyAttrValue keyCount:oVCnt zone:NULL];
+ if (self->connectionDictionary != nil) {
+ EOAdaptorGlobalID *agid = nil;
+
+ agid = [[EOAdaptorGlobalID alloc] initWithGlobalID:gid
+ connectionDictionary:
+ self->connectionDictionary];
+ AUTORELEASE(agid);
+ gid = agid;
+ }
+ [_obj takeValue:gid forKey:@"globalID"];
+ }
+
+ RELEASE(expression); expression = NULL;
+
+ /* mark datasource as changed */
+
+ [self postDataSourceChangedNotification];
+}
+
+- (void)updateObject:(id)_obj {
+ NSString *whereClause = nil;
+ NSMutableString *expression = nil;
+ EOAdaptor *adaptor = nil;
+ EOKeyGlobalID *gid = nil;
+ NSEnumerator *enumerator = nil;
+ NSString *tableName = nil;
+ EOAttribute *attr = nil;
+ BOOL isFirst = YES;
+ NSDictionary *objects = nil;
+ EOAdaptorChannel *adChan = nil;
+
+ BOOL localComTrans;
+
+ if ((gid = [_obj valueForKey:@"globalID"]) == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"missing globalID, couldn`t update"];
+ }
+ if ([gid isKindOfClass:[EOAdaptorGlobalID class]]) {
+ NSDictionary *conD = nil;
+
+ conD = [(EOAdaptorGlobalID *)gid connectionDictionary];
+ if (![conD isEqualToDictionary:self->connectionDictionary]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"try to update object %@ in "
+ @"wrong AdaptorDataSource %@", _obj, self];
+ }
+ gid = (EOKeyGlobalID *)[(EOAdaptorGlobalID *)gid globalID];
+ }
+ if ([[self->adChannel adaptorContext] hasOpenTransaction])
+ localComTrans = NO;
+ else
+ localComTrans = YES;
+
+ adChan = [self beginTransaction];
+ tableName = [gid entityName];
+ adaptor = [[adChan adaptorContext] adaptor];
+ whereClause = [self _whereClauseForGlobaID:gid adaptor:adaptor
+ channel:adChan];
+ if (whereClause == nil) {
+ [self rollbackTransaction];
+ return;
+ }
+ expression = [[NSMutableString alloc] initWithCapacity:256];
+ [expression appendString:@"UPDATE "];
+ [expression appendString:[gid entityName]];
+ [expression appendString:@" SET "];
+
+ objects = [self _mapAttrsWithValues:_obj tableName:tableName
+ channel:adChan];
+ enumerator = [objects keyEnumerator];
+
+ while ((attr = [enumerator nextObject])) {
+ id value;
+
+ if (isFirst)
+ isFirst = NO;
+ else
+ [expression appendString:@", "];
+ [expression appendString:[adaptor formatAttribute:attr]];
+ [expression appendString:@"="];
+
+ value = [objects objectForKey:attr];
+ if (value == nil) value = null;
+
+ [expression appendString:[adaptor formatValue:value forAttribute:attr]];
+ }
+ [expression appendString:@" WHERE "];
+ [expression appendString:whereClause];
+ if (![adChan evaluateExpression:expression]) {
+ [adChan cancelFetch];
+ [self rollbackTransaction];
+ AUTORELEASE(expression);
+ [[[EOAdaptorException alloc]
+ initWithFormat:@"evaluate expression %@ failed", expression] raise];
+ }
+ [adChan cancelFetch];
+ if (localComTrans)
+ [self commitTransaction];
+
+ RELEASE(expression); expression = nil;
+
+ {
+ EOGlobalID *newGID;
+ NSArray *attrs;
+ NSEnumerator *enumerator;
+ id *objs;
+ int objCnt;
+ NSString *attr;
+
+ attrs = [self _primaryKeyAttributeNamesForTableName:[gid entityName]
+ channel:adChan];
+ enumerator = [attrs objectEnumerator];
+ objCnt = 0;
+ objs = calloc([attrs count], sizeof(id));
+
+ while ((attr = [enumerator nextObject])) {
+ objs[objCnt] = [_obj valueForKey:attr];
+ objCnt++;
+ }
+ newGID = [EOKeyGlobalID globalIDWithEntityName:[gid entityName]
+ keys:objs keyCount:objCnt zone:NULL];
+ if (self->connectionDictionary != nil) {
+ newGID = [[EOAdaptorGlobalID alloc] initWithGlobalID:newGID
+ connectionDictionary:
+ self->connectionDictionary];
+ [newGID autorelease];
+ }
+ [_obj setObject:newGID forKey:@"globalID"];
+ }
+ [self postDataSourceChangedNotification];
+}
+
+- (void)deleteObject:(NSDictionary *)_obj {
+ NSString *whereClause = nil;
+ NSMutableString *expression = nil;
+ EOKeyGlobalID *gid = nil;
+ EOAdaptorChannel *adChan = nil;
+
+ BOOL localComTrans;
+
+ if ((gid = [_obj valueForKey:@"globalID"]) == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"missing globalID, could not delete"];
+ }
+ if ([gid isKindOfClass:[EOAdaptorGlobalID class]]) {
+ NSDictionary *conD = nil;
+
+ conD = [(EOAdaptorGlobalID *)gid connectionDictionary];
+ if (![conD isEqualToDictionary:self->connectionDictionary]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"try to delete object %@ in wrong "
+ @"AdaptorDataSource %@", _obj, self];
+ }
+ gid = (EOKeyGlobalID *)[(EOAdaptorGlobalID *)gid globalID];
+ }
+
+ if ([[self->adChannel adaptorContext] hasOpenTransaction])
+ localComTrans = NO;
+ else
+ localComTrans = YES;
+
+ adChan = [self beginTransaction];
+ whereClause = [self _whereClauseForGlobaID:gid
+ adaptor:[[adChan adaptorContext] adaptor] channel:adChan];
+ if (whereClause == nil) {
+ [self rollbackTransaction];
+ return;
+ }
+ expression = [[NSMutableString alloc] initWithCapacity:256];
+ [expression appendString:@"DELETE FROM "];
+ [expression appendString:[gid entityName]];
+ [expression appendString:@" WHERE "];
+ [expression appendString:whereClause];
+ if (![adChan evaluateExpression:expression]) {
+ [adChan cancelFetch];
+ [self rollbackTransaction];
+ AUTORELEASE(expression);
+ [[[EOAdaptorException alloc]
+ initWithFormat:@"couldn`t evaluate expression %@ failed",
+ expression] raise];
+ }
+ [adChan cancelFetch];
+ if (localComTrans)
+ [self commitTransaction];
+ RELEASE(expression); expression = nil;
+ [self postDataSourceChangedNotification];
+}
+
+- (void)setFetchSpecification:(EOFetchSpecification *)_fs {
+ if (![self->fetchSpecification isEqual:_fs]) {
+#if DEBUG && 0
+ NSLog(@"%s: 0x%08X: fetch-spec mismatch:\n%@\n%@",
+ __PRETTY_FUNCTION__, self,
+ self->fetchSpecification, _fs);
+#endif
+
+ ASSIGNCOPY(self->fetchSpecification, _fs);
+
+ [self postDataSourceItselfChangedNotification];
+ }
+#if DEBUG && 0
+ else {
+ NSLog(@"%s: 0x%08X: no fetch-spec mismatch:\n%@\n%@\n",
+ __PRETTY_FUNCTION__, self,
+ self->fetchSpecification, _fs);
+ }
+#endif
+}
+
+- (EOFetchSpecification *)fetchSpecification {
+ return [[self->fetchSpecification copy] autorelease];
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%@: adaptorChannel: %@",
+ [super description], self->adChannel];
+}
+
+@end /* EOAdaptorDataSource */
+
+@implementation EOAdaptorDataSource(Private)
+
+- (NSArray *)_primaryKeyAttributeNamesForTableName:(NSString *)_entityName
+ channel:(EOAdaptorChannel *)_adChannel
+{
+ NSDictionary *hints;
+ NSArray *attrs;
+
+ hints = [self->fetchSpecification hints];
+ attrs = [hints objectForKey:EOPrimaryKeyAttributeNamesHint];
+ if (attrs)
+ return attrs;
+
+ attrs = [hints objectForKey:EOPrimaryKeyAttributesHint];
+
+ if (attrs == nil) {
+ if (!(attrs = [_adChannel primaryKeyAttributesForTableName:_entityName])) {
+ attrs = [_adChannel attributesForTableName:_entityName];
+ }
+ }
+
+ attrs = [[attrs map:@selector(columnName)] map:@selector(lowercaseString)];
+ attrs = [attrs sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
+
+ return attrs;
+}
+
+- (NSArray *)_primaryKeyAttributesForTableName:(NSString *)_entityName
+ channel:(EOAdaptorChannel *)_adChannel
+{
+ NSArray *attrs;
+ NSDictionary *hints;
+
+ hints = [self->fetchSpecification hints];
+
+ attrs = [hints objectForKey:EOPrimaryKeyAttributesHint];
+ if (attrs != nil)
+ return attrs;
+
+ attrs = [hints objectForKey:EOPrimaryKeyAttributeNamesHint];
+ if (attrs != nil) {
+ NSArray *allAttrs;
+ NSEnumerator *enumerator;
+ id *objs;
+ int objCnt;
+ id obj;
+
+ allAttrs = [_adChannel attributesForTableName:_entityName];
+ objs = malloc(sizeof(id) * [allAttrs count]);
+ enumerator = [allAttrs objectEnumerator];
+
+ objCnt = 0;
+
+ while ((obj = [enumerator nextObject])) {
+ if ([attrs containsObject:[[obj columnName] lowercaseString]]) {
+ objs[objCnt++] = obj;
+ }
+ }
+ attrs = [NSArray arrayWithObjects:objs count:objCnt];
+ free(objs); objs = NULL;
+ return attrs;
+ }
+ if (!(attrs = [_adChannel primaryKeyAttributesForTableName:_entityName])) {
+ attrs = [_adChannel attributesForTableName:_entityName];
+ }
+ return attrs;
+}
+
+- (NSString *)_whereExprWithChannel:(EOAdaptorChannel *)_adChan {
+ EOQualifier *qual = nil;
+ NSArray *attrs = nil;
+ NSString *entityName = nil;
+ EOAdaptor *adaptor;
+
+ entityName = [self->fetchSpecification entityName];
+
+ if ((attrs = self->__attributes) == nil)
+ attrs = [_adChan attributesForTableName:entityName];
+
+ if ((qual = self->__qualifier) == nil)
+ qual = [self->fetchSpecification qualifier];
+
+ if (qual == nil)
+ return nil;
+
+ adaptor = [[_adChan adaptorContext] adaptor];
+
+ return [qual sqlExpressionWithAdaptor:adaptor attributes:attrs];
+}
+
+- (NSMutableString *)_selectListWithChannel:(EOAdaptorChannel *)_adChan {
+ NSArray *attrs = nil;
+ NSEnumerator *enumerator = nil;
+ EOAttribute *attribute = nil;
+ BOOL first = YES;
+ NSMutableString *select = nil;
+ EOAdaptor *adaptor = nil;
+ NSString *entityName = nil;
+
+ adaptor = [[_adChan adaptorContext] adaptor];
+ entityName = [self->fetchSpecification entityName];
+
+ if ((attrs = self->__attributes) == nil)
+ attrs = [_adChan attributesForTableName:entityName];
+
+ attrs = [_adChan _sortAttributesForSelectExpression:attrs];
+ select = [NSMutableString stringWithCapacity:128];
+ enumerator = [attrs objectEnumerator];
+ while ((attribute = [enumerator nextObject])) {
+ if (first)
+ first = NO;
+ else
+ [select appendString:@", "];
+
+ [select appendString:[adaptor formatAttribute:attribute]];
+ }
+ return select;
+}
+
+- (NSString *)_whereClauseForGlobaID:(EOKeyGlobalID *)_gid
+ adaptor:(EOAdaptor *)_adaptor
+ channel:(EOAdaptorChannel *)_adChan
+{
+ NSEnumerator *enumerator;
+ NSMutableString *result;
+ NSArray *pKeys;
+ NSArray *pkAttrs;
+ NSString *pKey;
+ int pkCnt;
+
+
+ pKeys = [self _primaryKeyAttributeNamesForTableName:[_gid entityName]
+ channel:_adChan];
+ pkAttrs = [self _primaryKeyAttributesForTableName:[_gid entityName]
+ channel:_adChan];
+
+
+ if ([pKeys count] != [_gid keyCount]) {
+ NSLog(@"ERROR[%s]: internal inconsitency pkeys %@ gid %@",
+ __PRETTY_FUNCTION__, pKeys, _gid);
+ return nil;
+ }
+ enumerator = [pKeys objectEnumerator];
+
+ pkCnt = 0;
+ result = nil;
+ while ((pKey = [enumerator nextObject])) {
+ EOAttribute *attr;
+ id value;
+
+ if (result == nil)
+ result = [NSMutableString stringWithCapacity:128];
+ else
+ [result appendString:@" AND "];
+
+ {
+ NSEnumerator *enumerator;
+
+ enumerator = [pkAttrs objectEnumerator];
+ while ((attr = [enumerator nextObject])) {
+ if ([[[attr columnName] lowercaseString] isEqual:pKey])
+ break;
+ }
+ NSAssert2(attr != nil, @"missing attribute for pkName %@ attrs %@",
+ pKey, pkAttrs);
+ }
+ [result appendString:[_adaptor formatAttribute:attr]];
+
+
+ value = [(EOKeyGlobalID *)_gid keyValues][pkCnt++];
+ if (value == nil) value = null;
+
+ [result appendString:[value isNotNull] ? @"=" : @" IS "];
+ [result appendString:[_adaptor formatValue:value forAttribute:attr]];
+ }
+ return result;
+}
+
+- (NSDictionary *)_mapAttrsWithValues:(id)_keyValues
+ tableName:(NSString *)_tableName
+ channel:(EOAdaptorChannel *)_adChan
+{
+ id *keys, *values;
+ int mapCnt;
+ NSEnumerator *en;
+ EOAttribute *attr;
+ NSDictionary *result;
+ NSArray *attrs;
+
+ attrs = [_adChan attributesForTableName:_tableName];
+ mapCnt = [attrs count];
+ keys = calloc(mapCnt, sizeof(id));
+ values = calloc(mapCnt, sizeof(id));
+ en = [attrs objectEnumerator];
+ mapCnt = 0;
+
+ while ((attr = [en nextObject])) {
+ id v;
+
+ v = (v = [_keyValues valueForKey:[[attr columnName] lowercaseString]])
+ ? v : null;
+
+ keys[mapCnt] = attr;
+ values[mapCnt] = v;
+ mapCnt++;
+ }
+ result = [[NSDictionary alloc]
+ initWithObjects:values forKeys:keys count:mapCnt];
+ free(keys); keys = NULL;
+ free(values); values = NULL;
+ return [result autorelease];
+}
+
+@end /* EOAdaptorDataSource(Private) */
+
+@implementation EOAndQualifier(SqlExpression)
+
+- (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor
+ attributes:(NSArray *)_attributes
+{
+ NSMutableString *str = nil;
+ NSEnumerator *enumerator = nil;
+ EOQualifier *qual = nil;
+ BOOL isFirst = YES;
+ NSString *result = nil;
+
+ str = [[NSMutableString alloc] initWithCapacity:128];
+
+ enumerator = [self->qualifiers objectEnumerator];
+ while ((qual = [enumerator nextObject])) {
+ NSString *s;
+
+ s = [qual sqlExpressionWithAdaptor:_adaptor attributes:_attributes];
+ if (isFirst) {
+ [str appendFormat:@"(%@)", s];
+ isFirst = NO;
+ }
+ else
+ [str appendFormat:@" AND (%@)", s];
+ }
+ result = [str copy];
+ [str release]; str = nil;
+ return [result autorelease];
+}
+@end /* EOAndQualifier(SqlExpression) */
+
+@implementation EOOrQualifier(SqlExpression)
+
+- (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor
+ attributes:(NSArray *)_attributes
+{
+ NSMutableString *str = nil;
+ NSEnumerator *enumerator = nil;
+ EOQualifier *qual = nil;
+ BOOL isFirst = YES;
+ NSString *result = nil;
+
+ str = [[NSMutableString alloc] initWithCapacity:128];
+
+ enumerator = [self->qualifiers objectEnumerator];
+ while ((qual = [enumerator nextObject])) {
+ NSString *s;
+
+ s = [qual sqlExpressionWithAdaptor:_adaptor attributes:_attributes];
+ if (isFirst) {
+ [str appendFormat:@"(%@)", s];
+ isFirst = NO;
+ }
+ else
+ [str appendFormat:@" OR (%@)", s];
+ }
+ result = [str copy];
+ [str release]; str = nil;
+ return [result autorelease];
+}
+
+@end /* EOOrQualifier(SqlExpression) */
+
+@implementation EOKeyValueQualifier(SqlExpression)
+
++ (NSString *)sqlStringForOperatorSelector:(SEL)_sel {
+ static NSMapTable *selectorToOperator = NULL;
+ NSString *s, *ss;
+
+ if ((s = NSStringFromSelector(_sel)) == nil)
+ return nil;
+
+ if (selectorToOperator == NULL) {
+ selectorToOperator = NSCreateMapTable(NSObjectMapKeyCallBacks,
+ NSObjectMapValueCallBacks,
+ 10);
+ NSMapInsert(selectorToOperator,
+ NSStringFromSelector(EOQualifierOperatorEqual),
+ @"=");
+ NSMapInsert(selectorToOperator,
+ NSStringFromSelector(EOQualifierOperatorNotEqual),
+ @"<>");
+ NSMapInsert(selectorToOperator,
+ NSStringFromSelector(EOQualifierOperatorLessThan),
+ @"<");
+ NSMapInsert(selectorToOperator,
+ NSStringFromSelector(EOQualifierOperatorGreaterThan),
+ @">");
+ NSMapInsert(selectorToOperator,
+ NSStringFromSelector(EOQualifierOperatorLessThanOrEqualTo),
+ @"<=");
+ NSMapInsert(selectorToOperator,
+ NSStringFromSelector(EOQualifierOperatorGreaterThanOrEqualTo),
+ @">=");
+ }
+
+ if ((ss = NSMapGet(selectorToOperator, s)))
+ return ss;
+
+ return nil;
+}
+
+- (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor
+ attributes:(NSArray *)_attributes
+{
+ EOAttribute *attr = nil;
+ NSEnumerator *en = nil;
+ NSString *k = nil;
+ NSString *sql = nil;
+ NSString *sqlKey, *sqlValue;
+
+ k = [self->key lowercaseString];
+ en = [_attributes objectEnumerator];
+
+ while ((attr = [en nextObject])) {
+ if ([[[attr columnName] lowercaseString] isEqualToString:k]) {
+ break;
+ }
+ }
+ if (!attr) {
+ en = [_attributes objectEnumerator];
+ while ((attr = [en nextObject])) {
+ if ([[attr name] isEqualToString:self->key])
+ break;
+ }
+ }
+ if (!attr) {
+ NSLog(@"WARNING[%s]: missing attribute [%@] for qualifier %@",
+ __PRETTY_FUNCTION__,
+ _attributes, self);
+ return @"1=2";
+ }
+
+ sqlKey = [_adaptor formatAttribute:attr];
+
+ sqlValue = [_adaptor formatValue:self->value ? self->value : null
+ forAttribute:attr];
+
+ sql = nil;
+
+ if (SEL_EQ(EOQualifierOperatorEqual, self->operator)) {
+ if ([self->value isNotNull])
+ sql = [NSString stringWithFormat:@"%@ = %@", sqlKey, sqlValue];
+ else
+ sql = [NSString stringWithFormat:@"%@ IS NULL", sqlKey];
+ }
+ else if (SEL_EQ(EOQualifierOperatorNotEqual, self->operator)) {
+ if ([self->value isNotNull])
+ sql = [NSString stringWithFormat:@"NOT (%@ = %@)", sqlKey, sqlValue];
+ else
+ sql = [NSString stringWithFormat:@"%@ IS NOT NULL", sqlKey];
+ }
+ else if (SEL_EQ(EOQualifierOperatorLessThan, self->operator)) {
+ sql = [NSString stringWithFormat:@"%@ < %@", sqlKey, sqlValue];
+ }
+ else if (SEL_EQ(EOQualifierOperatorLessThanOrEqualTo, self->operator)) {
+ sql = [NSString stringWithFormat:@"%@ <= %@", sqlKey, sqlValue];
+ }
+ else if (SEL_EQ(EOQualifierOperatorGreaterThan, self->operator)) {
+ sql = [NSString stringWithFormat:@"%@ > %@", sqlKey, sqlValue];
+ }
+ else if (SEL_EQ(EOQualifierOperatorGreaterThanOrEqualTo, self->operator)) {
+ sql = [NSString stringWithFormat:@"%@ >= %@", sqlKey, sqlValue];
+ }
+ else if (SEL_EQ(EOQualifierOperatorLike, self->operator)) {
+ sqlValue = [[self->value stringValue]
+ stringByReplacingString:@"*" withString:@"%"];
+ sqlValue = [_adaptor formatValue:sqlValue forAttribute:attr];
+
+ sql = [NSString stringWithFormat:@"%@ LIKE %@", sqlKey, sqlValue];
+ }
+ else if (SEL_EQ(EOQualifierOperatorCaseInsensitiveLike, self->operator)) {
+ sqlValue = [[self->value stringValue]
+ stringByReplacingString:@"*" withString:@"%"];
+ sqlValue = [sqlValue lowercaseString];
+ sqlValue = [_adaptor formatValue:sqlValue forAttribute:attr];
+
+ sql = [NSString stringWithFormat:@"LOWER(%@) LIKE %@", sqlKey, sqlValue];
+ }
+#if 0
+ else if (SEL_EQ(EOQualifierOperatorLessThanOrEqualTo, self->operator)) {
+ }
+ else if (SEL_EQ(EOQualifierOperatorGreaterThanOrEqualTo, self->operator)) {
+ }
+#endif
+ else {
+ NSLog(@"ERROR(%s): unsupported SQL operator: %@", __PRETTY_FUNCTION__,
+ [EOQualifier stringForOperatorSelector:self->operator]);
+ [self notImplemented:_cmd];
+ return nil;
+ }
+
+ return sql;
+}
+
+@end /* EOKeyValueQualifier(SqlExpression) */
+
+@implementation EONotQualifier(SqlExpression)
+
+- (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor
+ attributes:(NSArray *)_attributes
+{
+ NSString *s;
+
+ s = [self->qualifier sqlExpressionWithAdaptor:_adaptor
+ attributes:_attributes];
+ return [NSString stringWithFormat:@"NOT(%@)", s];
+}
+
+@end /* EONotQualifier(SqlExpression) */
+
+@implementation EOKeyComparisonQualifier(SqlExpression)
+
+- (NSString *)sqlExpressionWithAdaptor:(EOAdaptor *)_adaptor
+ attributes:(NSArray *)_attributes
+{
+ NSLog(@"ERROR(%s): subclass needs to override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+@end /* EOKeyComparisonQualifier(SqlExpression) */
--- /dev/null
+/*
+ EOArrayProxy.h
+
+ Copyright (C) 1999 MDlink online service center GmbH, Helge Hess
+
+ Author: Helge Hess (hh@mdlink.de)
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAdaptorGlobalID.m 1 2004-08-20 10:38:46Z znek $
+
+#include <GDLAccess/EOAdaptorGlobalID.h>
+#include "common.h"
+
+@implementation EOAdaptorGlobalID
+
+- (id)initWithGlobalID:(EOGlobalID *)_gid
+ connectionDictionary:(NSDictionary *)_conDict
+{
+ if ((self = [super init])) {
+ ASSIGN(self->gid, _gid);
+ ASSIGN(self->conDict, _conDict);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->gid);
+ RELEASE(self->conDict);
+ [super dealloc];
+}
+
+- (EOGlobalID *)globalID {
+ return self->gid;
+}
+
+- (NSDictionary *)connectionDictionary {
+ return self->conDict;
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)_zone {
+ return RETAIN(self);
+}
+
+/* equality */
+
+- (BOOL)isEqual:(id)_obj {
+ if ([_obj isKindOfClass:[EOAdaptorGlobalID class]])
+ return [self isEqualToEOAdaptorGlobalID:_obj];
+ return NO;
+}
+
+- (BOOL)isEqualToEOAdaptorGlobalID:(EOAdaptorGlobalID *)_gid {
+ if ([[_gid globalID] isEqual:self->gid] &&
+ [[_gid connectionDictionary] isEqual:self->conDict])
+ return YES;
+
+ return NO;
+}
+
+/* description */
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%@: globalID: %@ connectionDictionary: %@",
+ [super description], self->gid, self->conDict];
+}
+
+@end /* SkyDBGlobalKey */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAdaptorOperation.m 1 2004-08-20 10:38:46Z znek $
+
+#include <GDLAccess/EOAdaptorOperation.h>
+#include "common.h"
+
+@implementation EOAdaptorOperation
+@end /* EOAdaptorOperation */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOAndQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $
+
+#import "EOSQLQualifier.h"
+#include "common.h"
+
+@implementation EOAndQualifier(SQLQualifier)
+
+/* SQL qualifier generation */
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity {
+ unsigned cc = [self->qualifiers count];
+
+ if (cc == 0) {
+ return nil;
+ }
+ else if (cc == 1) {
+ return [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity];
+ }
+ else if (cc == 2) {
+ id left;
+ id right;
+
+ left = [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity];
+ right = [[self->qualifiers objectAtIndex:1] sqlQualifierForEntity:_entity];
+ [left conjoinWithQualifier:right];
+ return left;
+ }
+ else {
+ EOSQLQualifier *masterQ;
+ unsigned i;
+
+ for (i = 0, masterQ = nil; i < cc; i++) {
+ EOSQLQualifier *q;
+
+ q = [[self->qualifiers objectAtIndex:i]
+ sqlQualifierForEntity:_entity];
+ if (masterQ == nil)
+ masterQ = q;
+ else
+ [masterQ conjoinWithQualifier:q];
+ }
+ return masterQ;
+ }
+}
+
+@end /* EOAndQualifier */
--- /dev/null
+/*
+ EOArrayProxy.m
+
+ Copyright (C) 1999 MDlink online service center GmbH, Helge Hess
+
+ Author: Helge Hess (hh@mdlink.de)
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOArrayProxy.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOArrayProxy.h"
+#import "EODatabaseChannel.h"
+#import "EODatabaseContext.h"
+#import "EOEntity.h"
+#import "EOSQLQualifier.h"
+#import "EOGenericRecord.h"
+
+@implementation EOArrayProxy
+
+- (id)initWithQualifier:(EOSQLQualifier *)_qualifier
+ fetchOrder:(NSArray *)_fetchOrder
+ channel:(EODatabaseChannel *)_channel
+{
+ self->qualifier = RETAIN(_qualifier);
+ self->fetchOrder = RETAIN(_fetchOrder);
+ self->channel = RETAIN(_channel);
+ return self;
+}
+
++ (id)arrayProxyWithQualifier:(EOSQLQualifier *)_qualifier
+ fetchOrder:(NSArray *)_fetchOrder
+ channel:(EODatabaseChannel *)_channel
+{
+ return AUTORELEASE([[self alloc] initWithQualifier:_qualifier
+ fetchOrder:_fetchOrder
+ channel:_channel]);
+}
+
+- (void)dealloc {
+ AUTORELEASE(self->content);
+ RELEASE(self->qualifier);
+ RELEASE(self->fetchOrder);
+ RELEASE(self->channel);
+ [super dealloc];
+}
+
+// accessors
+
+- (BOOL)isFetched {
+ return self->content ? YES : NO;
+}
+
+- (EODatabaseChannel *)databaseChannel {
+ return self->channel;
+}
+- (EOEntity *)entity {
+ return [self->qualifier entity];
+}
+- (NSArray *)fetchOrder {
+ return self->fetchOrder;
+}
+- (EOSQLQualifier *)qualifier {
+ return self->qualifier;
+}
+
+// operations
+
+- (void)clear {
+ RELEASE(self->content);
+ self->content = nil;
+}
+
+- (BOOL)fetch {
+ BOOL inTransaction;
+ BOOL didOpenChannel;
+ NSMutableArray *result;
+
+ [self clear];
+ result = [NSMutableArray arrayWithCapacity:16];
+
+ didOpenChannel = (![self->channel isOpen])
+ ? [self->channel openChannel]
+ : NO;
+
+ if ([self->channel isFetchInProgress]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"attempt to fetch with busy channel: %@", self];
+ }
+
+ inTransaction =
+ [[self->channel databaseContext] transactionNestingLevel] > 0;
+ if (!inTransaction) {
+ if (![[self->channel databaseContext] beginTransaction]) {
+ NSLog(@"WARNING: could not begin transaction to fetch array proxy !");
+
+ if (didOpenChannel)
+ [self->channel closeChannel];
+ return NO;
+ }
+ }
+
+ if (![self->channel selectObjectsDescribedByQualifier:self->qualifier
+ fetchOrder:self->fetchOrder]) {
+ if (!inTransaction)
+ [[self->channel databaseContext] rollbackTransaction];
+ if (didOpenChannel)
+ [self->channel closeChannel];
+
+ NSLog(@"ERROR: select on array proxy failed ..");
+ return NO;
+ }
+
+ { // fetch objects
+ NSZone *z = [self zone];
+ id object;
+
+ while ((object = [self->channel fetchWithZone:z]))
+ [result addObject:object];
+ object = nil;
+ }
+ [self->channel cancelFetch];
+
+ if (!inTransaction) {
+ if (![[self->channel databaseContext] commitTransaction]) {
+ NSLog(@"WARNING: could not commit array proxy's transaction !");
+
+ if (didOpenChannel)
+ [self->channel closeChannel];
+ return NO;
+ }
+ }
+
+ if (didOpenChannel)
+ [self->channel closeChannel];
+
+ self->content = [result copyWithZone:[self zone]];
+ return YES;
+}
+
+// turn fault to real array ..
+
+void _checkFetch(EOArrayProxy *self) {
+ if (self->content) return;
+ [self fetch];
+}
+
+// NSArray operations
+
+- (id)objectAtIndex:(unsigned int)_index {
+ _checkFetch(self);
+ return [self->content objectAtIndex:_index];
+}
+- (unsigned int)count {
+ _checkFetch(self);
+ return [self->content count];
+}
+- (unsigned int)indexOfObjectIdenticalTo:(id)_object {
+ _checkFetch(self);
+ return [self->content indexOfObjectIdenticalTo:_object];
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone {
+ if (NSShouldRetainWithZone(self, zone))
+ return RETAIN(self);
+ else {
+ _checkFetch(self);
+ return [[NSArray allocWithZone:zone] initWithArray:self->content copyItems:NO];
+ }
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone {
+ _checkFetch(self);
+ return [[NSMutableArray alloc] initWithArray:self->content];
+}
+
+
+#if 0
+
+// forwarding
+
+- (void)forwardInvocation:(NSInvocation *)_invocation {
+ _checkFetch(self);
+ [_invocation invokeWithTarget:self->content];
+}
+
+- (retval_t)forward:(SEL)_selector:(arglist_t)_frame {
+ _checkFetch(self);
+ return objc_msg_sendv(self->content, _selector, _frame);
+}
+
+#endif
+
+@end
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOAttribute.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOAttribute.h"
+#import "EOModel.h"
+#import "EOEntity.h"
+#import "EORelationship.h"
+#import "EOExpressionArray.h"
+#import "EOCustomValues.h"
+#import <EOControl/EONull.h>
+#import "EOFExceptions.h"
+
+@interface NSString(BeautifyAttributeName)
+
+- (NSString *)_beautifyAttributeName;
+
+@end
+
+@implementation EOAttribute
+
+static NSString *defaultCalendarFormat = @"%b %d %Y %H:%M";
+static EONull *null = nil;
+
++ (void)initialize {
+ if (null == nil)
+ null = [[EONull null] retain];
+}
+
+- (id)initWithName:(NSString*)_name {
+ if ((self = [super init])) {
+ ASSIGN(self->name,_name);
+ self->entity = nil;
+ }
+ return self;
+}
+- (id)init {
+ return [self initWithName:nil];
+}
+
+- (void)dealloc {
+ RELEASE(self->name);
+ RELEASE(self->calendarFormat);
+ RELEASE(self->clientTimeZone);
+ RELEASE(self->serverTimeZone);
+ RELEASE(self->columnName);
+ RELEASE(self->definition);
+ RELEASE(self->externalType);
+ RELEASE(self->valueClassName);
+ RELEASE(self->valueType);
+ RELEASE(self->insertFormat);
+ RELEASE(self->selectFormat);
+ RELEASE(self->updateFormat);
+ RELEASE(self->userDictionary);
+ self->entity = nil; /* non-retained */
+ RELEASE(self->definitionArray);
+ RELEASE(self->realAttribute);
+ [super dealloc];
+}
+
+// These methods should be here to let the library work with NeXT foundation
+- (id)copy {
+ return RETAIN(self);
+}
+- (id)copyWithZone:(NSZone *)_zone {
+ return RETAIN(self);
+}
+
+// Is equal only if same name; used to make aliasing ordering stable
+- (unsigned)hash {
+ return [self->name hash];
+}
+
+- (BOOL)setName:(NSString*)_name {
+ if([name isEqual:_name])
+ return YES;
+
+ if([entity attributeNamed:_name])
+ return NO;
+
+ ASSIGN(name, _name);
+ return YES;
+}
+
++ (BOOL)isValidName:(NSString*)_name {
+ return [EOEntity isValidName:_name];
+}
+
+- (BOOL)setReadOnly:(BOOL)flag {
+ if(!flag && ([self isDerived] || [self isFlattened]))
+ return NO;
+ flags.isReadOnly = flag;
+ return YES;
+}
+
+- (BOOL)referencesProperty:(id)property {
+ return (flags.isDerived)
+ ? [self->definitionArray indexOfObject:property] != NSNotFound
+ : NO;
+}
+
+- (void)setDefinition:(NSString *)def {
+ NSArray *defArray;
+ int i, count;
+ EOEntity *currentEntity;
+ id realAttributeName;
+
+ if (def == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"invalid (nil) definition argument!"];
+ }
+
+ self->flags.isDerived = YES;
+ self->flags.isFlattened = NO;
+
+ ASSIGN(self->definition, def);
+
+ if ([definition isNameOfARelationshipPath]) {
+ self->flags.isFlattened = YES;
+ defArray = [definition componentsSeparatedByString:@"."];
+ count = [defArray count];
+
+ RELEASE(self->definitionArray);
+ self->definitionArray = [[NSMutableArray alloc] initWithCapacity:count];
+
+ NS_DURING {
+ currentEntity = self->entity;
+
+ for (i = 0; i < count - 1; i++) {
+ id relationshipName, relationship;
+
+ relationshipName = [defArray objectAtIndex:i];
+
+ if(![EOEntity isValidName:relationshipName]) {
+ [[[InvalidNameException alloc]
+ initWithName:relationshipName] raise];
+ }
+
+ relationship
+ = [currentEntity relationshipNamed:relationshipName];
+
+ if(relationship == nil) {
+ [[[InvalidPropertyException alloc]
+ initWithName:relationshipName entity:currentEntity] raise];
+ }
+ if([relationship isToMany]) {
+ [[[RelationshipMustBeToOneException alloc]
+ initWithName:relationshipName entity:currentEntity] raise];
+ }
+ [self->definitionArray addObject:relationship];
+ currentEntity = [relationship destinationEntity];
+ }
+ realAttributeName = [defArray lastObject];
+
+ RELEASE(self->realAttribute);
+ self->realAttribute =
+ RETAIN([currentEntity attributeNamed:realAttributeName]);
+ if (self->realAttribute == nil) {
+ [[[InvalidPropertyException alloc]
+ initWithName:realAttributeName entity:currentEntity] raise];
+ }
+ [self->definitionArray addObject:self->realAttribute];
+ }
+ NS_HANDLER {
+ RELEASE(self->definitionArray);
+ self->definitionArray = nil;
+ [localException raise];
+ }
+ NS_ENDHANDLER;
+ }
+ else {
+ [self->definitionArray release];
+ self->definitionArray = nil;
+ self->definitionArray
+ = [[EOExpressionArray parseExpression:definition
+ entity:entity
+ replacePropertyReferences:YES]
+ retain];
+ }
+}
+
+- (NSString *)expressionValueForContext:(id<EOExpressionContext>)context {
+ return (context)
+ ? [context expressionValueForAttribute:self]
+ : columnName;
+}
+
+- (void)setEntity:(EOEntity*)_entity {
+ self->entity = _entity; /* non-retained */
+}
+- (EOEntity *)entity {
+ return self->entity;
+}
+- (void)resetEntity {
+ self->entity = nil;
+}
+- (BOOL)hasEntity {
+ return (self->entity != nil) ? YES : NO;
+}
+
+- (void)setCalendarFormat:(NSString*)format {
+ ASSIGN(self->calendarFormat, format);
+}
+- (NSString *)calendarFormat {
+ return self->calendarFormat;
+}
+
+- (void)setClientTimeZone:(NSTimeZone*)tz {
+ ASSIGN(self->clientTimeZone, tz);
+}
+- (NSTimeZone *)clientTimeZone {
+ return self->clientTimeZone;
+}
+
+- (void)setServerTimeZone:(NSTimeZone*)tz {
+ ASSIGN(self->serverTimeZone, tz);
+}
+- (NSTimeZone *)serverTimeZone {
+ return self->serverTimeZone;
+}
+
+- (void)setColumnName:(NSString*)_name {
+ ASSIGN(self->columnName, _name);
+}
+- (NSString *)columnName {
+ return self->columnName;
+}
+
+- (void)setExternalType:(NSString*)type {
+ ASSIGN(self->externalType, type);
+}
+- (NSString *)externalType {
+ return ((self->externalType == nil) && self->flags.isFlattened)
+ ? [self->realAttribute externalType]
+ : self->externalType;
+}
+
+- (void)setValueClassName:(NSString *)_name {
+ ASSIGN(self->valueClassName, _name);
+}
+- (NSString *)valueClassName {
+ return ((self->valueClassName == nil) && self->flags.isFlattened)
+ ? [self->realAttribute valueClassName]
+ : self->valueClassName;
+}
+
+- (void)setValueType:(NSString *)type {
+ ASSIGN(self->valueType, type);
+}
+- (NSString *)valueType {
+ return ((self->valueType == nil) && self->flags.isFlattened)
+ ? [self->realAttribute valueType]
+ : self->valueType;
+}
+
+- (void)setInsertFormat:(NSString *)string {
+ ASSIGN(self->insertFormat, string);
+}
+- (NSString *)insertFormat {
+ return self->insertFormat;
+}
+
+- (void)setSelectFormat:(NSString *)string {
+ ASSIGN(self->selectFormat, string);
+}
+- (NSString *)selectFormat {
+ return self->selectFormat;
+}
+
+- (void)setUpdateFormat:(NSString*)string {
+ ASSIGN(self->updateFormat, string);
+}
+- (NSString *)updateFormat {
+ return self->updateFormat;
+}
+
+- (void)setUserDictionary:(NSDictionary *)dict {
+ ASSIGN(self->userDictionary, dict);
+}
+- (NSDictionary *)userDictionary {
+ return self->userDictionary;
+}
+
++ (NSString *)defaultCalendarFormat {
+ return defaultCalendarFormat;
+}
+- (NSString *)name {
+ return self->name;
+}
+- (NSString *)definition {
+ return self->definition;
+}
+- (NSMutableArray *)definitionArray {
+ return self->definitionArray;
+}
+- (BOOL)isDerived {
+ return self->flags.isDerived;
+}
+- (BOOL)isFlattened {
+ return self->flags.isFlattened;
+}
+
+- (BOOL)isReadOnly {
+ return self->flags.isDerived ? YES : self->flags.isReadOnly;
+}
+
+/* description */
+
+- (NSString *)description {
+ return [[self propertyList] description];
+}
+
+@end /* EOAttribute */
+
+
+@implementation EOAttribute (EOAttributePrivate)
+
++ (EOAttribute*)attributeFromPropertyList:(id)propertyList {
+ EOAttribute *attribute = nil;
+ NSString *timeZoneName;
+ id tmp;
+
+ attribute = [[EOAttribute alloc] init];
+ AUTORELEASE(attribute);
+
+ [attribute setName:[propertyList objectForKey:@"name"]];
+ [attribute setCalendarFormat:[propertyList objectForKey:@"calendarFormat"]];
+
+ timeZoneName = [propertyList objectForKey:@"clientTimeZone"];
+ if (timeZoneName)
+ [attribute setClientTimeZone:[NSTimeZone timeZoneWithName:timeZoneName]];
+
+ timeZoneName = [propertyList objectForKey:@"serverTimeZone"];
+ if (timeZoneName)
+ [attribute setServerTimeZone:[NSTimeZone timeZoneWithName:timeZoneName]];
+
+ [attribute setColumnName: [propertyList objectForKey:@"columnName"]];
+ [attribute setExternalType: [propertyList objectForKey:@"externalType"]];
+ [attribute setValueClassName:[propertyList objectForKey:@"valueClassName"]];
+ [attribute setValueType: [propertyList objectForKey:@"valueType"]];
+ [attribute setInsertFormat: [propertyList objectForKey:@"insertFormat"]];
+ [attribute setSelectFormat: [propertyList objectForKey:@"selectFormat"]];
+ [attribute setUpdateFormat: [propertyList objectForKey:@"updateFormat"]];
+ [attribute setUserDictionary:[propertyList objectForKey:@"userDictionary"]];
+
+ [attribute setReadOnly:
+ [[propertyList objectForKey:@"isReadOnly"] isEqual:@"Y"]];
+
+ if ((tmp = [propertyList objectForKey:@"allowsNull"]))
+ [attribute setAllowsNull:[tmp isEqual:@"Y"]];
+ else
+ [attribute setAllowsNull:YES];
+
+ [attribute setWidth:
+ [[propertyList objectForKey:@"width"] unsignedIntValue]];
+
+ /* Don't call setDefinition: now. The attributes array in
+ entity is not yet set. */
+ attribute->definition = RETAIN([propertyList objectForKey:@"definition"]);
+
+ return attribute;
+}
+
+/* WARNING: You should call this method from entity after the relationships
+ were constructed and after the `attributes' array contains the real
+ attributes. */
+- (void)replaceStringsWithObjects {
+ if(self->definition) {
+ NS_DURING
+ [self setDefinition:self->definition];
+ NS_HANDLER {
+ //CATCH(PropertyDefinitionException)
+ NSLog([localException reason]);
+ [[self->entity model] errorInReading];
+ }
+ NS_ENDHANDLER;
+ }
+}
+
+- (id)propertyList {
+ NSMutableDictionary *propertyList;
+
+ propertyList = [NSMutableDictionary dictionaryWithCapacity:16];
+ [self encodeIntoPropertyList:propertyList];
+ return propertyList;
+}
+
+- (int)compareByName:(EOAttribute *)_other {
+ return [[(EOAttribute *)self name] compare:[_other name]];
+}
+
+@end /* EOAttribute (EOAttributePrivate) */
+
+@implementation EOAttribute(ValuesConversion)
+
+- (id)convertValue:(id)aValue toClass:(Class)aClass forType:(NSString*)_type {
+ // Check nil/EONull
+ if (aValue == nil)
+ return nil;
+ if (aValue == [EONull null])
+ return aValue;
+
+ // Check if we need conversion; we use is kind of because
+ // a string is not a NSString but some concrete class, so is NSData,
+ // NSNumber and may be other classes
+ if ([aValue isKindOfClass:aClass])
+ return aValue;
+
+ // We have to convert the aValue
+
+ // Try EOCustomValues
+ if ([aValue respondsToSelector:@selector(stringForType:)]) {
+ // Special case if aClass is NSNumber
+ if (aClass == [NSNumber class]) {
+ return [NSNumber
+ numberWithString:[aValue stringForType:_type]
+ type:_type];
+ }
+
+ // Even more Special case if aClass is NSCalendar date
+ if (aClass == [NSCalendarDate class]) {
+ id format, date;
+
+ format = [self calendarFormat];
+ if (format == nil)
+ format = [EOAttribute defaultCalendarFormat];
+ date = [NSCalendarDate
+ dateWithString:[aValue stringForType:_type]
+ calendarFormat:format];
+ [date setCalendarFormat:format];
+ return date;
+ }
+
+ // See if we can alloc a new aValue and initilize it
+ if ([aClass instancesRespondToSelector:
+ @selector(initWithString:type:)]) {
+ return AUTORELEASE([[aClass alloc]
+ initWithString:[aValue stringForType:_type]
+ type:_type]);
+ }
+ }
+
+ // Try EODatabaseCustomValues
+ if ([aValue respondsToSelector:@selector(dataForType:)]) {
+ // See if we can alloc a new aValue and initilize it
+ if ([aClass instancesRespondToSelector:
+ @selector(initWithData:type:)]) {
+ return AUTORELEASE([[aClass alloc]
+ initWithData:[aValue dataForType:_type]
+ type:_type]);
+ }
+ }
+
+ // Could not convert if got here
+ return nil;
+}
+
+- (id)convertValueToModel:(id)aValue {
+ id aValueClassName;
+ Class aValueClass;
+
+ // Check value class from attribute
+ aValueClassName = [self valueClassName];
+ aValueClass = NSClassFromString(aValueClassName);
+ if (aValueClass == Nil)
+ return aValue;
+
+ return [self convertValue:aValue
+ toClass:aValueClass forType:[self valueType]];
+}
+
+@end
+
+@implementation NSString (EOAttributeTypeCheck)
+
+- (BOOL)isNameOfARelationshipPath {
+ BOOL result = NO;
+ char buf[[self cStringLength] + 1];
+ const char *s;
+
+ s = buf;
+ [self getCString:buf];
+
+ if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#')
+ return NO;
+
+ for(++s; *s; s++) {
+ if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#' && *s != '$'
+ && *s != '.')
+ return NO;
+ if(*s == '.')
+ result = YES;
+ }
+
+ return result;
+}
+
+@end
+
+@implementation EOAttribute(PropertyListCoding)
+
+static inline void _addToPropList(NSMutableDictionary *propertyList,
+ id _value, NSString *key) {
+ if (_value) [propertyList setObject:_value forKey:key];
+}
+
+- (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist {
+ _addToPropList(_plist, self->name, @"name");
+ _addToPropList(_plist, self->calendarFormat, @"calendarFormat");
+ _addToPropList(_plist, self->columnName, @"columnName");
+ _addToPropList(_plist, self->definition, @"definition");
+ _addToPropList(_plist, self->externalType, @"externalType");
+ _addToPropList(_plist, self->valueClassName, @"valueClassName");
+ _addToPropList(_plist, self->valueType, @"valueType");
+ _addToPropList(_plist, self->insertFormat, @"insertFormat");
+ _addToPropList(_plist, self->selectFormat, @"selectFormat");
+ _addToPropList(_plist, self->updateFormat, @"updateFormat");
+ _addToPropList(_plist, self->userDictionary, @"userDictionary");
+
+ if (self->clientTimeZone) {
+ [_plist setObject:[self->clientTimeZone timeZoneName]
+ forKey:@"clientTimeZone"];
+ }
+ if (self->serverTimeZone) {
+ [_plist setObject:[self->serverTimeZone timeZoneName]
+ forKey:@"serverTimeZone"];
+ }
+
+ if (self->width != 0) {
+ [_plist setObject:[NSNumber numberWithUnsignedInt:self->width]
+ forKey:@"width"];
+ }
+
+ if (self->flags.isReadOnly) {
+ [_plist setObject:[NSString stringWithCString:"Y"]
+ forKey:@"isReadOnly"];
+ }
+ if (self->flags.allowsNull) {
+ [_plist setObject:[NSString stringWithCString:"Y"]
+ forKey:@"allowsNull"];
+ }
+}
+
+@end /* EOAttribute(PropertyListCoding) */
+
+@implementation EOAttribute(EOF2Additions)
+
+- (void)beautifyName {
+ [self setName:[[self name] _beautifyAttributeName]];
+}
+
+/* constraints */
+
+- (void)setAllowsNull:(BOOL)_flag {
+ self->flags.allowsNull = _flag ? 1 : 0;
+}
+- (BOOL)allowsNull {
+ return self->flags.allowsNull ? YES : NO;
+}
+
+- (void)setWidth:(unsigned)_width {
+ self->width = _width;
+}
+- (unsigned)width {
+ return self->width;
+}
+
+- (NSException *)validateValue:(id *)_value {
+ if (_value == NULL) return nil;
+
+ /* check NULL constraint */
+ if (!self->flags.allowsNull) {
+ if ((*_value == nil) || (*_value == null)) {
+ NSException *e;
+ NSDictionary *ui;
+
+ ui = [NSDictionary dictionaryWithObjectsAndKeys:
+ *_value ? *_value : null, @"value",
+ self, @"attribute",
+ nil];
+
+ e = [NSException exceptionWithName:@"EOValidationException"
+ reason:@"violated not-null constraint"
+ userInfo:ui];
+ return e;
+ }
+ }
+
+ /* check width constraint */
+
+ if (self->width != 0) {
+ static Class NSDataClass = Nil;
+ static Class NSStringClass = Nil;
+
+ if (NSDataClass == nil) NSDataClass = [NSData class];
+ if (NSStringClass == nil) NSStringClass = [NSString class];
+
+ if ([[*_value class] isKindOfClass:NSDataClass]) {
+ unsigned len;
+
+ len = [*_value length];
+ if (len > self->width) {
+ NSException *e;
+ NSDictionary *ui;
+
+ ui = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithUnsignedInt:self->width],
+ @"maxWidth",
+ [NSNumber numberWithUnsignedInt:len], @"width",
+ *_value ? *_value : null, @"value",
+ self, @"attribute",
+ nil];
+
+ e = [NSException exceptionWithName:@"EOValidationException"
+ reason:@"data value exceeds allowed attribute width"
+ userInfo:ui];
+ return e;
+ }
+ }
+ else if ([[*_value class] isKindOfClass:NSStringClass]) {
+ unsigned len;
+
+ len = [*_value cStringLength];
+ if (len > self->width) {
+ NSException *e;
+ NSDictionary *ui;
+
+ ui = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithUnsignedInt:self->width],
+ @"maxWidth",
+ [NSNumber numberWithUnsignedInt:len], @"width",
+ *_value ? *_value : null, @"value",
+ self, @"attribute",
+ nil];
+
+ e = [NSException exceptionWithName:@"EOValidationException"
+ reason:@"string value exceeds allowed attribute width"
+ userInfo:ui];
+ return e;
+ }
+ }
+ }
+
+ return nil;
+}
+
+- (NSString *)readFormat {
+ return nil;
+}
+- (NSString *)writeFormat {
+ return nil;
+}
+
+@end /* EOAttribute(EOF2Additions) */
+
+@implementation NSString(BeautifyAttributeName)
+
+- (NSString *)_beautifyAttributeName {
+ unsigned clen = 0;
+ char *s = NULL;
+ unsigned cnt, cnt2;
+
+ if ([self length] == 0)
+ return @"";
+
+ clen = [self cStringLength];
+#if GNU_RUNTIME
+ s = objc_atomic_malloc(clen + 4);
+#else
+ s = malloc(clen + 4);
+#endif
+
+ [self getCString:s maxLength:clen];
+
+ for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) {
+ if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = toupper(s[cnt + 1]);
+ cnt++;
+ }
+ else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = s[cnt];
+ cnt++;
+ cnt2++;
+ s[cnt2] = toupper(s[cnt]);
+ }
+ else
+ s[cnt2] = tolower(s[cnt]);
+ }
+ s[cnt2] = '\0';
+
+#if !LIB_FOUNDATION_LIBRARY
+ {
+ NSString *os;
+
+ os = [NSString stringWithCString:s];
+ free(s);
+ return os;
+ }
+#else
+ return [NSString stringWithCStringNoCopy:s freeWhenDone:YES];
+#endif
+}
+
+@end /* NSString(BeautifyAttributeName) */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import <GDLAccess/EOAttribute.h>
+#import <GDLAccess/EOAttributeOrdering.h>
+#import "common.h"
+
+@implementation EOAttributeOrdering
+
++ (id)attributeOrderingWithAttribute:(EOAttribute*)_attribute
+ ordering:(EOOrdering)_ordering
+{
+ return AUTORELEASE([[EOAttributeOrdering alloc]
+ initWithAttribute:_attribute ordering:_ordering]);
+}
+
+- (id)initWithAttribute:(EOAttribute*)_attribute ordering:(EOOrdering)_ordering {
+ ASSIGN(self->attribute, _attribute);
+ self->ordering = _ordering;
+ return self;
+}
+
+- (EOAttribute *)attribute {
+ return self->attribute;
+}
+- (EOOrdering)ordering {
+ return self->ordering;
+}
+
+@end /* EOAttributeOrdering */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOCustomValues.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOCustomValues.h"
+
+@implementation NSString(EOCustomValues)
+
++ stringWithString:(NSString*)string type:(NSString*)type {
+ // If mutable return a copy if not return self
+
+ if ([string isKindOfClass:[NSMutableString class]])
+ return [[NSString alloc] initWithString:string type:type];
+ else
+ return RETAIN(self);
+}
+
+- initWithString:(NSString*)string type:(NSString*)type {
+ return [self initWithString:string];
+}
+
+- (NSString*)stringForType:(NSString*)type {
+ // If mutable return a copy if not return self (handled in NSString)
+ return [self copyWithZone:[self zone]];
+}
+
+- (id)initWithData:(NSData*)data type:(NSString*)type {
+ return [self initWithCString:[data bytes] length:[data length]];
+}
+
+- (NSData *)dataForType:(NSString *)type {
+ unsigned len = [self cStringLength];
+ char buf[len + 1];
+ [self getCString:buf];
+ return [NSData dataWithBytes:buf length:len];
+}
+
+@end /* NSString(EOCustomValues) */
+
+
+@implementation NSData(EOCustomValues)
+
+- (id)initWithString:(NSString*)string type:(NSString*)type {
+ unsigned len = [string cStringLength];
+ char buf[len + 1];
+ [string getCString:buf];
+
+ return [self initWithBytes:buf length:len];
+}
+
+- (NSString*)stringForType:(NSString*)type {
+ return [NSString stringWithCString:[self bytes] length:[self length]];
+}
+
+- initWithData:(NSData*)data type:(NSString*)type {
+ return [self initWithBytes:[data bytes] length:[data length]];
+}
+
+- (NSData*)dataForType:(NSString*)type {
+ return [self copyWithZone:[self zone]];
+}
+
+@end /* NSData(EOCustomValues) */
+
+
+@implementation NSNumber(EOCustomValues)
+
++ (id)numberWithString:(NSString*)string type:(NSString*)type {
+ char buf[[string cStringLength] + 1];
+ const char *cstring;
+
+ [string getCString:buf];
+ cstring = buf;
+
+ if ([type cStringLength] == 1)
+ switch ((unsigned char)[type characterAtIndex:0]) {
+ case 'c' : {
+ char value = atoi(cstring);
+ return [NSNumber numberWithChar:value];
+ }
+ case 'C' : {
+ unsigned char value = atoi(cstring);
+ return [NSNumber numberWithUnsignedChar:value];
+ }
+ case 's' : {
+ short value = atoi(cstring);
+ return [NSNumber numberWithShort:value];
+ }
+ case 'S' : {
+ unsigned short value = atoi(cstring);
+ return [NSNumber numberWithUnsignedShort:value];
+ }
+ case 'i' : {
+ int value = atoi(cstring);
+ return [NSNumber numberWithInt:value];
+ }
+ case 'I' : {
+ unsigned int value = atoi(cstring);
+ return [NSNumber numberWithUnsignedInt:value];
+ }
+ case 'l' : {
+ long value = atol(cstring);
+ return [NSNumber numberWithLong:value];
+ }
+ case 'L' : {
+ unsigned long value = atol(cstring);
+ return [NSNumber numberWithUnsignedLong:value];
+ }
+ case 'q' : {
+ long long value = atol(cstring);
+ return [NSNumber numberWithLongLong:value];
+ }
+ case 'Q' : {
+ unsigned long long value = atol(cstring);
+ return [NSNumber numberWithUnsignedLongLong:value];
+ }
+ case 'f' : {
+ float value = atof(cstring);
+ return [NSNumber numberWithFloat:value];
+ }
+ case 'd' : {
+ double value = atof(cstring);
+ return [NSNumber numberWithDouble:value];
+ }
+ }
+
+ [NSException raise:NSInvalidArgumentException
+ format:@"invalid type `%@' for NSNumber in "
+ @"numberWithString:type:", type];
+ return nil;
+}
+
+- initWithString:(NSString*)string type:(NSString*)type {
+ (void)AUTORELEASE(self);
+ return RETAIN([NSNumber numberWithString:string type:type]);
+}
+
+- (NSString*)stringForType:(NSString*)type {
+ return [self stringValue];
+}
+
+@end /* NSNumber(EOCustomValues) */
+
+void EOAccess_EOCustomValues_link(void) {
+ EOAccess_EOCustomValues_link();
+}
--- /dev/null
+/*
+ EODatabase.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EODatabase.h"
+#import "EOAdaptor.h"
+#import "EOModel.h"
+#import "EOEntity.h"
+#import "EOGenericRecord.h"
+#import "EODatabaseContext.h"
+#import "EOObjectUniquer.h"
+#import "EODatabaseFault.h"
+
+NSTimeInterval NSDistantPastTimeInterval = 0.0;
+
+@implementation EODatabase
+
+// Database Global Methods
+
+static NSMutableArray *databaseInstances = nil;
+static NSRecursiveLock *lock = nil;
+
++ (void)initialize {
+ static BOOL isInitialized = NO;
+ // THREAD
+ if (!isInitialized) {
+ isInitialized = YES;
+ databaseInstances = [[NSMutableArray alloc] init];
+ lock = [[NSRecursiveLock alloc] init];
+ }
+}
+
+static inline void _addDatabaseInstance(EODatabase *_db) {
+ [lock lock];
+ [databaseInstances addObject:[NSValue valueWithNonretainedObject:_db]];
+ [lock unlock];
+}
+static inline void _removeDatabaseInstance(EODatabase *_db) {
+ [lock lock];
+ {
+ int i;
+
+ for (i = [databaseInstances count] - 1; i >= 0; i--) {
+ EODatabase *db;
+
+ db = [[databaseInstances objectAtIndex:i] nonretainedObjectValue];
+ if (db == _db) {
+ [databaseInstances removeObjectAtIndex:i];
+ break;
+ }
+ }
+ }
+ [lock unlock];
+}
+
+/*
+ * Initializing new instances
+ */
+
+- (id)initWithAdaptor:(EOAdaptor *)_adaptor {
+ if (_adaptor == nil) {
+ AUTORELEASE(self);
+ return nil;
+ }
+
+ self->adaptor = RETAIN(_adaptor);
+ self->objectsDictionary = [[EOObjectUniquer allocWithZone:[self zone]] init];
+ self->contexts = [[NSMutableArray allocWithZone:[self zone]] init];
+
+ self->flags.isUniquingObjects = YES;
+ self->flags.isKeepingSnapshots = YES;
+ self->flags.isLoggingWarnings = YES;
+
+ _addDatabaseInstance(self);
+
+ return self;
+}
+
+- (id)initWithModel:(EOModel *)_model {
+ return [self initWithAdaptor:[EOAdaptor adaptorWithModel:_model]];
+}
+- (id)init {
+ return [self initWithAdaptor:nil];
+}
+
+- (void)dealloc {
+ _removeDatabaseInstance(self);
+
+ RELEASE(self->adaptor);
+ RELEASE(self->objectsDictionary);
+ RELEASE(self->contexts);
+ [super dealloc];
+}
+
+// accessors
+
+- (EOAdaptor *)adaptor {
+ return self->adaptor;
+}
+
+- (EOObjectUniquer *)objectUniquer {
+ return self->objectsDictionary;
+}
+
+// Checking connection status
+
+- (BOOL)hasOpenChannels {
+ int i;
+
+ for (i = ([self->contexts count] - 1); i >= 0; i--) {
+ if ([[[self->contexts objectAtIndex:i] nonretainedObjectValue]
+ hasOpenChannels])
+ return YES;
+ }
+ return NO;
+}
+
+/*
+ * Getting the database contexts
+ */
+
+- (id)createContext {
+ return AUTORELEASE([[EODatabaseContext alloc] initWithDatabase:self]);
+}
+
+- (NSArray *)contexts {
+ NSMutableArray *array = nil;
+ int i, n;
+
+ n = [self->contexts count];
+ array = [[NSMutableArray alloc] initWithCapacity:n];
+
+ for (i = 0; i < n; i++) {
+ EODatabaseContext *ctx;
+
+ ctx = [[self->contexts objectAtIndex:i] nonretainedObjectValue];
+ [array addObject:ctx];
+ }
+ return AUTORELEASE(array);
+}
+
+- (void)contextDidInit:(id)_context {
+ [self->contexts addObject:[NSValue valueWithNonretainedObject:_context]];
+}
+
+- (void)contextWillDealloc:(id)aContext {
+ int i;
+
+ for (i = [self->contexts count]-1; i >= 0; i--) {
+ if ([[self->contexts objectAtIndex:i] nonretainedObjectValue] == aContext) {
+ [self->contexts removeObjectAtIndex:i];
+ break;
+ }
+ }
+}
+
+/*
+ * Uniquing/snapshotting
+ */
+
+- (void)setUniquesObjects:(BOOL)yn {
+ if ([self hasOpenChannels]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabase:%x: All channels must be closed when changing "
+ @"uniquing mode in the EODatabase, "
+ @"in [EODatabase setUniquesObjects:]",
+ self];
+ }
+
+ if ((!yn) && (self->flags.isUniquingObjects))
+ [self->objectsDictionary forgetAllObjects];
+ self->flags.isUniquingObjects = yn;
+}
+- (BOOL)uniquesObjects {
+ return self->flags.isUniquingObjects;
+}
+
+- (void)setKeepsSnapshots:(BOOL)yn {
+ if ([self hasOpenChannels]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabase:%x: All channels must be closed when changing "
+ @"snapshoting mode in the EODatabase, "
+ @"in [EODatabase setKeepsSnapshots:]",
+ self];
+ }
+
+ if ((yn == NO) && self->flags.isKeepingSnapshots)
+ [self->objectsDictionary forgetAllSnapshots];
+
+ self->flags.isKeepingSnapshots = yn;
+}
+- (BOOL)keepsSnapshots {
+ return self->flags.isKeepingSnapshots;
+}
+
+// ******************** Handle Objects ********************
+
+- (void)forgetAllObjects {
+ [self->objectsDictionary forgetAllObjects];
+}
+
++ (void)forgetObject:(id)_object {
+ [EOObjectUniquer forgetObject:_object];
+
+ [lock lock];
+ {
+ int i;
+
+ for (i = [databaseInstances count] - 1; i >= 0; i--) {
+ EODatabase *db;
+
+ db = [[databaseInstances objectAtIndex:i] nonretainedObjectValue];
+ [db forgetObject:_object];
+ }
+ }
+ [lock unlock];
+}
+
+- (void)forgetObject:(id)_object {
+ /*
+ NSLog(@"DB[0x%08X]: forget object 0x%08X<%s> entity=%@",
+ self, _object, class_get_class_name(*(Class *)_object),
+ [[_object entity] name]);
+ */
+ [self->objectsDictionary forgetObject:_object];
+}
+
+- (void)forgetAllSnapshots {
+ [self->objectsDictionary forgetAllSnapshots];
+}
+
+- (id)objectForPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity {
+ if (self->flags.isUniquingObjects && (_key != nil) && (_entity != nil)) {
+ _key = [_entity primaryKeyForRow:_key];
+ if (_key == nil)
+ return nil;
+ else {
+ id object = [self->objectsDictionary objectForPrimaryKey:_key entity:_entity];
+
+#if 0
+ if (object) {
+ if (![object isKindOfClass:[EOGenericRecord class]])
+ NSLog(@"object 0x%08X pkey=%@ entity=%@", object, _key, _entity);
+ }
+#endif
+ return object;
+ }
+ }
+ return nil;
+}
+
+- (NSDictionary *)snapshotForObject:_object {
+ EOUniquerRecord* rec = [self->objectsDictionary recordForObject:_object];
+
+ return rec ? rec->snapshot : nil;
+}
+
+- (NSDictionary *)primaryKeyForObject:(id)_object {
+ EOUniquerRecord* rec = [self->objectsDictionary recordForObject:_object];
+
+ return rec ? rec->pkey : nil;
+}
+
+- (void)primaryKey:(NSDictionary**)_key
+ andSnapshot:(NSDictionary**)_snapshot
+ forObject:(id)_object {
+
+ EOUniquerRecord *rec = [self->objectsDictionary recordForObject:_object];
+
+ if (rec) {
+ if (_key) *_key = rec->pkey;
+ if (_snapshot) *_snapshot = rec->snapshot;
+ }
+ else {
+ if (_key) *_key = nil;
+ if (_snapshot) *_snapshot = nil;
+ }
+}
+
+- (void)recordObject:(id)_object
+ primaryKey:(NSDictionary *)_key
+ snapshot:(NSDictionary *)_snapshot {
+
+ EOEntity *entity;
+
+ entity = [_object respondsToSelector:@selector(entity)]
+ ? [_object entity]
+ : [[self->adaptor model] entityForObject:_object];
+
+ [self recordObject:_object
+ primaryKey:_key
+ entity:entity
+ snapshot:_snapshot];
+}
+
+- (void)recordObject:(id)_object
+ primaryKey:(NSDictionary *)_key
+ entity:(EOEntity *)_entity
+ snapshot:(NSDictionary *)_snapshot {
+
+ if (_object == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabase:%x: Cannot record null object, "
+ @"in [EODatabase recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+ if ((_entity == nil) && self->flags.isUniquingObjects) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabase:%x: Cannot record object with null entity "
+ @"when the database is uniquing objects, "
+ @"in [EODatabase recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+ _key = [_entity primaryKeyForRow:_key];
+ if ((_key == nil) && self->flags.isUniquingObjects) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabase:%x: Cannot record object with null key "
+ @"when the database is uniquing objects, "
+ @"in [EODatabase recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+ if ((_snapshot == nil) && self->flags.isKeepingSnapshots) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabase:%x: Cannot record object with null snapshot "
+ @"when the database is keeping snapshots, "
+ @"in [EODatabase recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+
+ [objectsDictionary recordObject:_object
+ primaryKey:self->flags.isUniquingObjects?_key:nil
+ entity:self->flags.isUniquingObjects ?_entity:nil
+ snapshot:self->flags.isKeepingSnapshots?_snapshot:nil];
+}
+
+- (BOOL)isObject:(id)_object
+ updatedOutsideContext:(EODatabaseContext *)_context
+{
+ int i;
+
+ for (i = [contexts count] - 1; i >= 0; i--) {
+ EODatabaseContext *ctx;
+
+ ctx = [[self->contexts objectAtIndex:i] nonretainedObjectValue];
+
+ if ((ctx != _context) && [ctx isObjectUpdated:_object])
+ return YES;
+ }
+ return NO;
+}
+
+// ******************** Error messages ********************
+
+- (void)setLogsErrorMessages:(BOOL)yn {
+ self->flags.isLoggingWarnings = yn;
+}
+- (BOOL)logsErrorMessages {
+ return self->flags.isLoggingWarnings;
+}
+
+- (void)reportErrorFormat:(NSString*)format, ... {
+ va_list va;
+
+ va_start(va, format);
+ [self reportErrorFormat:format arguments:va];
+ va_end(va);
+}
+
+- (void)reportErrorFormat:(NSString*)format arguments:(va_list)arguments {
+ [self reportError:AUTORELEASE([[NSString alloc] initWithFormat:format
+ arguments:arguments])];
+}
+
+- (void)reportError:(NSString*)error {
+ if (self->flags.isLoggingWarnings)
+ NSLog(@"EODatabase:%x:%@", self, error);
+}
+
+@end /* EODatabase */
+
+@implementation EODatabase(EOF2Additions)
+
+- (NSArray *)models {
+ EOModel *model;
+
+ model = [[self adaptor] model];
+ return model ? [NSArray arrayWithObject:model] : nil;
+}
+
+- (void)addModel:(EOModel *)_model {
+ EOModel *model;
+
+ model = [[self adaptor] model];
+
+ if (model == nil)
+ [[self adaptor] setModel:_model];
+ else
+ [self notImplemented:_cmd];
+}
+
+- (BOOL)addModelIfCompatible:(EOModel *)_model {
+ NSEnumerator *e;
+ EOModel *m;
+
+ if (![[self adaptor] canServiceModel:_model])
+ return NO;
+
+ e = [[self models] objectEnumerator];
+ while ((m = [e nextObject])) {
+ if (m == _model)
+ return YES;
+
+ if (![[m adaptorName] isEqualToString:[_model adaptorName]])
+ return NO;
+ }
+
+ [self addModel:_model];
+ return YES;
+}
+
+- (EOEntity *)entityForObject:(id)_object {
+ return [[[self adaptor] model] entityForObject:_object];
+}
+- (EOEntity *)entityNamed:(NSString *)_name {
+ return [[[self adaptor] model] entityNamed:_name];
+}
+
+/* snapshots */
+
+- (void)forgetSnapshotsForGlobalIDs:(NSArray *)_gids {
+ NSEnumerator *e;
+ EOGlobalID *gid;
+
+ e = [_gids objectEnumerator];
+ while ((gid = [e nextObject]))
+ [self forgetSnapshotsForGlobalID:gid];
+}
+- (void)forgetSnapshotsForGlobalID:(EOGlobalID *)_gid {
+ [self notImplemented:_cmd];
+}
+
+- (void)recordSnapshot:(NSDictionary *)_snapshot forGlobalID:(EOGlobalID *)_gid {
+ [self notImplemented:_cmd];
+}
+- (void)recordSnapshots:(NSDictionary *)_snapshots {
+ NSEnumerator *gids;
+ EOGlobalID *gid;
+
+ gids = [_snapshots keyEnumerator];
+ while ((gid = [gids nextObject]))
+ [self recordSnapshot:[_snapshots objectForKey:gid] forGlobalID:gid];
+}
+
+- (void)recordSnapshot:(NSArray *)_gids
+ forSourceGlobalID:(EOGlobalID *)_gid
+ relationshipName:(NSString *)_name
+{
+ /* to-many snapshot */
+ [self notImplemented:_cmd];
+}
+- (void)recordToManySnapshots:(NSDictionary *)_snapshots {
+ NSEnumerator *gids;
+ EOGlobalID *gid;
+
+ gids = [_snapshots keyEnumerator];
+ while ((gid = [gids nextObject])) {
+ NSDictionary *d;
+ NSEnumerator *relNames;
+ NSString *relName;
+
+ d = [_snapshots objectForKey:gid];
+ relNames = [d keyEnumerator];
+
+ while ((relName = [relNames nextObject])) {
+ [self recordSnapshot:[d objectForKey:relName]
+ forSourceGlobalID:gid
+ relationshipName:relName];
+ }
+ }
+}
+
+- (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid
+ after:(NSTimeInterval)_duration
+{
+ NSLog(@"ERROR(%s): subclasses must override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+- (NSDictionary *)snapshotForGlobalID:(EOGlobalID *)_gid {
+ return [self snapshotForGlobalID:_gid after:NSDistantPastTimeInterval];
+}
+
+@end /* EODatabase(EOF2Additions) */
--- /dev/null
+/*
+ EODatabaseChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EODatabaseChannel.h"
+#import "EOAdaptor.h"
+#import "EOAdaptorChannel.h"
+#import "EOAdaptorContext.h"
+#import "EOAttribute.h"
+#import "EODatabase.h"
+#import "EODatabaseContext.h"
+#import "EOEntity.h"
+#import "EODatabaseFault.h"
+#import "EOGenericRecord.h"
+#import "EOModel.h"
+#import "EOObjectUniquer.h"
+#import "EOSQLQualifier.h"
+#import "EORelationship.h"
+#import <EOControl/EONull.h>
+#import <EOControl/EOFetchSpecification.h>
+#import <EOControl/EOKeyValueCoding.h>
+
+@class EOGenericRecord;
+
+NSString *EODatabaseChannelWillOpenNotificationName =
+ @"EODatabaseChannelWillOpenNotification";
+NSString *EODatabaseChannelDidOpenNotificationName =
+ @"EODatabaseChannelDidOpenNotification";
+NSString *EODatabaseChannelWillCloseNotificationName =
+ @"EODatabaseChannelWillCloseNotification";
+NSString *EODatabaseChannelDidCloseNotificationName =
+ @"EODatabaseChannelDidCloseNotification";
+NSString *EODatabaseChannelCouldNotOpenNotificationName =
+ @"EODatabaseChannelCouldNotOpenNotification";
+NSString *EODatabaseChannelWillInsertObjectName =
+ @"EODatabaseChannelWillInsertObjectName";
+NSString *EODatabaseChannelDidInsertObjectName =
+ @"EODatabaseChannelDidInsertObjectName";
+NSString *EODatabaseChannelWillUpdateObjectName =
+ @"EODatabaseChannelWillUpdateObjectName";
+NSString *EODatabaseChannelDidUpdateObjectName =
+ @"EODatabaseChannelDidUpdateObjectName";
+NSString *EODatabaseChannelWillDeleteObjectName =
+ @"EODatabaseChannelWillDeleteObjectName";
+NSString *EODatabaseChannelDidDeleteObjectName =
+ @"EODatabaseChannelDidDeleteObjectName";
+NSString *EODatabaseChannelWillLockObjectName =
+ @"EODatabaseChannelWillLockObjectName";
+NSString *EODatabaseChannelDidLockObjectName =
+ @"EODatabaseChannelDidLockObjectName";
+
+/*
+ * Private methods declaration
+ */
+
+@interface EODatabaseChannel(Private)
+- (id)privateFetchWithZone:(NSZone *)_zone;
+- (Class)privateClassForEntity:(EOEntity *)anEntity;
+- (void)privateUpdateCurrentEntityInfo;
+- (void)privateClearCurrentEntityInfo;
+- (void)privateReportError:(SEL)method:(NSString *)format, ...;
+@end
+
+/*
+ * EODatabaseChannel implementation
+ */
+
+@implementation EODatabaseChannel
+
+/*
+ * Initializing a new instance
+ */
+
+- (id)initWithDatabaseContext:(EODatabaseContext *)_dbContext {
+ if (_dbContext == nil) {
+ AUTORELEASE(self);
+ return nil;
+ }
+
+ self->notificationCenter = RETAIN([NSNotificationCenter defaultCenter]);
+
+ self->databaseContext = RETAIN(_dbContext);
+ [self setDelegate:[self->databaseContext delegate]];
+ [self->databaseContext channelDidInit:self];
+
+ return self;
+}
+
+- (void)dealloc {
+ [self->databaseContext channelWillDealloc:self];
+ RELEASE(self->currentEditingContext);
+ RELEASE(self->databaseContext);
+ RELEASE(self->adaptorChannel);
+ RELEASE(self->notificationCenter);
+ [super dealloc];
+}
+
+// notifications
+
+- (void)postNotification:(NSString *)_name {
+ [self->notificationCenter postNotificationName:_name object:self];
+}
+- (void)postNotification:(NSString *)_name object:(id)_obj {
+ [self->notificationCenter postNotificationName:_name
+ object:self
+ userInfo:[NSDictionary dictionaryWithObject:_obj
+ forKey:@"object"]];
+}
+
+// accessors
+
+- (EOAdaptorChannel *)adaptorChannel {
+ if (self->adaptorChannel == nil) {
+ static int reuseAdaptorCh = -1;
+ if (reuseAdaptorCh == -1) {
+ reuseAdaptorCh = [[[NSUserDefaults standardUserDefaults]
+ objectForKey:@"EOReuseAdaptorChannel"]
+ boolValue] ? 1 : 0;
+ }
+
+ if (reuseAdaptorCh) {
+ NSEnumerator *channels;
+ EOAdaptorChannel *channel;
+
+ channels =
+ [[[[self databaseContext] adaptorContext] channels] objectEnumerator];
+
+ while ((channel = [channels nextObject])) {
+ if ([channel isFetchInProgress])
+ continue;
+
+#if DEBUG
+ NSLog(@"reuse adaptor channel: %@", channel);
+#endif
+ self->adaptorChannel = channel;
+ break;
+ }
+ }
+
+ if (self->adaptorChannel == nil) {
+ self->adaptorChannel =
+ [[[self databaseContext] adaptorContext] createAdaptorChannel];
+ }
+
+ RETAIN(self->adaptorChannel);
+ }
+ return self->adaptorChannel;
+}
+
+- (EODatabaseContext *)databaseContext {
+ return self->databaseContext;
+}
+
+// delegate
+
+- (void)setDelegate:(id)_delegate {
+ self->delegate = _delegate;
+}
+- (id)delegate {
+ return self->delegate;
+}
+
+// Opening and closing a channel
+
+- (BOOL)isOpen {
+ return [[self adaptorChannel] isOpen];
+}
+
+- (BOOL)openChannel {
+ BOOL result;
+
+ [self postNotification:EODatabaseChannelWillOpenNotificationName];
+
+ if ((result = [[self adaptorChannel] openChannel])) {
+ self->successfulOpenCount++;
+ [self postNotification:EODatabaseChannelDidOpenNotificationName];
+ }
+ else {
+ self->failedOpenCount++;
+ [self postNotification:EODatabaseChannelCouldNotOpenNotificationName];
+ }
+
+ return result;
+}
+
+- (void)closeChannel {
+ [self postNotification:EODatabaseChannelWillCloseNotificationName];
+ [[self adaptorChannel] closeChannel];
+ self->closeCount++;
+ [self postNotification:EODatabaseChannelDidCloseNotificationName];
+}
+
+// Modifying objects
+
+- (BOOL)_isNoRaiseOnModificationException:(NSException *)_exception {
+ /* for compatibility with non-X methods, translate some errors to a bool */
+ NSString *n;
+
+ n = [_exception name];
+ if ([n isEqualToString:@"EOEvaluationError"])
+ return YES;
+ if ([n isEqualToString:@"EODelegateRejects"])
+ return YES;
+
+ return NO;
+}
+
+- (BOOL)insertObject:(id)anObj {
+ // TODO: split up this method
+ // TODO: write an insertObjectX: which returns an exception
+ NSException *exception = nil;
+ EOEntity *entity = nil;
+ NSDictionary *pkey = nil;
+ NSDictionary *values = nil;
+ NSDictionary *snapshot = nil;
+ NSArray *attributes = nil;
+ int i;
+
+ [self postNotification:EODatabaseChannelWillInsertObjectName object:anObj];
+
+ if (![anObj prepareForInsertInChannel:self context:self->databaseContext])
+ return NO;
+
+ // Check the delegate
+ if ([self->delegate respondsToSelector:
+ @selector(databaseChannel:willInsertObject:)])
+ anObj = [delegate databaseChannel:self willInsertObject:anObj];
+
+ // Check nil (delegate disallowes or given object was nil)
+ if (anObj == nil)
+ return NO;
+
+ // Check if fault
+ if ([EOFault isFault:anObj]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Attempt to insert a fault in a database channel"];
+ }
+
+ // Check if we can insert
+ if ([databaseContext updateStrategy] == EONoUpdate) {
+ [self privateReportError:_cmd :
+ @"cannot insert if context has 'NoUpdate' update strategy."];
+ return NO;
+ }
+
+ /* validate object for insert */
+
+ if ((exception = [anObj validateForInsert])) {
+ /* validation failed */
+ [exception raise];
+ }
+
+ // Check if in a transaction
+ if (![databaseContext transactionNestingLevel]) {
+ [self privateReportError:_cmd :
+ @"cannot insert if contex has no transaction opened."];
+ return NO;
+ }
+
+ // Get entity
+ entity = [anObj respondsToSelector:@selector(entity)]
+ ? [anObj entity]
+ : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj];
+
+ // Check entity
+ if (entity == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine entity for object %p class %@.",
+ anObj, NSStringFromClass([anObj class])];
+ return NO;
+ }
+ if ([entity isReadOnly]) {
+ [self privateReportError:_cmd :
+ @"cannot insert object %p for readonly entity %@.",
+ anObj, [entity name]];
+ return NO;
+ }
+
+ // Get array of attributes to insert
+ attributes = [entity attributesUsedForInsert];
+
+ // Get simple values and convert them to adaptor values
+ values = [anObj valuesForKeys:[entity attributesNamesUsedForInsert]];
+ values = [entity convertValuesToModel:values];
+
+ // Get and check *must insert* attributes (primary key, lock, readonly)
+ for (i = [attributes count]-1; i >= 0; i--) {
+ EOAttribute *attribute = [attributes objectAtIndex:i];
+
+ NSAssert(attribute, @"invalid attribute object ..");
+
+ if (![values objectForKey:[attribute name]]) {
+ [self privateReportError:_cmd :
+ @"null value for insert attribute %@ for object %@ entity %@",
+ [attribute name], anObj, [entity name]];
+ return NO;
+ }
+ }
+
+ // Make primary key and snapshot
+ snapshot = [entity snapshotForRow:values];
+ if (snapshot == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine snapshot for %p from values %@ entity %@.",
+ anObj, [values description], [entity name]];
+ return NO;
+ }
+ pkey = [entity primaryKeyForRow:values];
+ if (pkey == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine primary key for %p from values %@ entity %@.",
+ anObj, [values description], [entity name]];
+ return NO;
+ }
+
+ // Insert adaptor row
+ exception = [adaptorChannel insertRowX:values forEntity:entity];
+ if (exception) {
+ if (![self _isNoRaiseOnModificationException:exception]) [exception raise];
+ return NO;
+ }
+
+ // Record object in database context
+ [databaseContext recordObject:anObj
+ primaryKey:pkey entity:entity snapshot:values];
+
+ self->insertCount++;
+ [anObj wasInsertedInChannel:self context:self->databaseContext];
+
+ // Notify delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:didInsertObject:)])
+ [delegate databaseChannel:self didInsertObject:anObj];
+
+ [self postNotification:EODatabaseChannelDidInsertObjectName object:anObj];
+ return YES;
+}
+
+- (BOOL)updateObject:(id)anObj {
+ // TODO: split up this huge method
+ // TODO: make an updateObjectX: method which returns an exception
+ NSException *exception = nil;
+ EOEntity *entity = nil;
+ EOSQLQualifier *qualifier = nil;
+ NSDictionary *old_pkey = nil;
+ NSDictionary *old_snapshot = nil;
+ NSDictionary *new_pkey = nil;
+ NSDictionary *new_snapshot = nil;
+ NSDictionary *values = nil;
+ BOOL needsOptimisticLock;
+
+ [self postNotification:EODatabaseChannelWillUpdateObjectName object:anObj];
+
+ if (![anObj prepareForUpdateInChannel:self context:self->databaseContext])
+ return NO;
+
+ // Check the delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:willUpdateObject:)])
+ anObj = [delegate databaseChannel:self willUpdateObject:anObj];
+
+ // Check nil (delegate disallowes or given object was nil)
+ if (anObj == nil)
+ return NO;
+
+ // Check if fault
+ if ([EOFault isFault:anObj]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Attempt to update a fault in a database channel"];
+ }
+
+ // Check if we can update
+ if ([databaseContext updateStrategy] == EONoUpdate) {
+ [self privateReportError:_cmd :
+ @"cannot update if context has 'NoUpdate' update strategy."];
+ return NO;
+ }
+
+ /* validate object for update */
+
+ if ((exception = [anObj validateForUpdate])) {
+ /* validation failed */
+ [exception raise];
+ }
+
+ // Check if in a transaction
+ if (![databaseContext transactionNestingLevel]) {
+ [self privateReportError:_cmd :
+ @"cannot update if contex has no transaction opened."];
+ return NO;
+ }
+
+ // Get entity
+ entity = [anObj respondsToSelector:@selector(entity)]
+ ? [anObj entity]
+ : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj];
+
+ // Check entity
+ {
+ if (entity == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine entity for object %p class %@.",
+ anObj, NSStringFromClass([anObj class])];
+ return NO;
+ }
+ if ([entity isReadOnly]) {
+ [self privateReportError:_cmd :
+ @"cannot update object %p for readonly entity %@.",
+ anObj, [entity name]];
+ return NO;
+ }
+ }
+
+ // Get and check old snapshot and primary key
+ {
+ [databaseContext primaryKey:&old_pkey
+ andSnapshot:&old_snapshot
+ forObject:anObj];
+
+ if (old_snapshot == nil) {
+ [self privateReportError:_cmd :
+ @"cannot update object %p because there is no snapshot for it."];
+ return NO;
+ }
+ if (old_pkey == nil)
+ old_pkey = [entity primaryKeyForRow:old_snapshot];
+ if (old_pkey == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine primary key for %p from snapshot %@ entity %@.",
+ anObj, [old_snapshot description], [entity name]];
+ return NO;
+ }
+ }
+
+ // Get simple values and convert them to adaptor values
+ values = [anObj valuesForKeys:[entity attributesNamesUsedForInsert]];
+ values = [entity convertValuesToModel:values];
+
+ // Get and check new primary key and snapshot
+ {
+ new_snapshot = [entity snapshotForRow:values];
+ if (new_snapshot == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine snapshot for %p from values %@ entity %@.",
+ anObj, [values description], [entity name]];
+ return NO;
+ }
+ new_pkey = [entity primaryKeyForRow:new_snapshot];
+ if (new_pkey == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine primary key for %p from values %@ entity %@.",
+ anObj, [values description], [entity name]];
+ return NO;
+ }
+ }
+
+ // Check if we need to lock optimistic before update
+ // that is compare locking attributes with the existing ones in database
+ switch([databaseContext updateStrategy]) {
+ case EOUpdateWithOptimisticLocking:
+ case EOUpdateWithPessimisticLocking:
+ needsOptimisticLock = ![databaseContext isObjectLocked:anObj];
+ break;
+ case EOUpdateWithNoLocking:
+ needsOptimisticLock = NO;
+ break;
+ default:
+ return NO;
+ }
+
+ // If we need an "optimistic lock" then perform lock
+ // else just make the qualifier based on the primary key only
+ if (needsOptimisticLock) {
+ int i;
+ BOOL canUseQualifier = YES;
+ NSArray *lockAttrs = [entity attributesUsedForLocking];
+ EOAdaptor *adaptor = [[adaptorChannel adaptorContext] adaptor];
+ NSDictionary *row;
+
+ // Check if attributes used for locking can be used in a qualifier
+ for (i = [lockAttrs count]-1; i >= 0; i--) {
+ if (![adaptor isValidQualifierType:
+ [[lockAttrs objectAtIndex:i] externalType]]) {
+ canUseQualifier = NO;
+ break;
+ }
+ }
+
+ if (canUseQualifier)
+ // If YES just build the qualifier
+ qualifier = [EOSQLQualifier qualifierForRow:old_snapshot
+ entity:entity];
+ else {
+ // If NO then lock the row in the database server, fetch the
+ // new snapshot and compare it with the old one
+ qualifier = [EOSQLQualifier qualifierForPrimaryKey:old_pkey
+ entity:entity];
+#ifdef DEBUG
+ NSAssert2([lockAttrs count] > 0,
+ @"missing locking attributes: lock=%@ object=%@",
+ lockAttrs, anObj);
+#endif
+ if (![adaptorChannel selectAttributes:lockAttrs
+ describedByQualifier:qualifier
+ fetchOrder:nil
+ lock:YES]) {
+ [self privateReportError:_cmd :
+ @"could not lock=%@ with qualifier=%@ entity=%@.",
+ anObj, [qualifier description], [entity name]];
+ return NO;
+ }
+ row = [adaptorChannel fetchAttributes:lockAttrs withZone:NULL];
+ [adaptorChannel cancelFetch];
+ if (row == nil) {
+ [self privateReportError:_cmd :
+ @"could not get row to lock %p with qualifier %@.",
+ anObj, [qualifier description]];
+ return NO;
+ }
+ [databaseContext recordLockedObject:anObj];
+ if (![row isEqual:old_snapshot]) {
+ [self privateReportError:_cmd :
+ @"could not lock %p. Snapshots: self %@ database %@.",
+ anObj, [old_snapshot description], [row description]];
+ return NO;
+ }
+ }
+ }
+ else {
+ qualifier = [EOSQLQualifier qualifierForPrimaryKey:old_pkey
+ entity:entity];
+ }
+
+ // Compute values as delta from values and old_snapshot
+ {
+ NSMutableDictionary *delta;
+ NSString *attributeName;
+ NSArray *allKeys;
+ int i, count;
+
+ allKeys = [values allKeys];
+ delta = [NSMutableDictionary dictionary];
+ for (i = 0, count = [allKeys count]; i < count; i++) {
+ id new_v, old_v;
+
+ attributeName = [allKeys objectAtIndex:i];
+ new_v = [values objectForKey:attributeName];
+ old_v = [old_snapshot objectForKey:attributeName];
+
+ if ((old_v == nil) || ![new_v isEqual:old_v])
+ [delta setObject:new_v forKey:attributeName];
+ }
+ values = delta;
+ }
+
+ // no reason for update --> fetch to be sure, that no one has deleted it
+ // HH: The object was not changed, so we refetch to determine whether it
+ // was deleted
+ if ([values count] == 0) {
+ if (![self refetchObject:anObj])
+ return NO;
+ }
+ // Update in adaptor
+ else {
+ NSException *ex;
+
+ ex = [adaptorChannel updateRowX:values describedByQualifier:qualifier];
+ if (ex != nil) {
+ if (![self _isNoRaiseOnModificationException:ex]) [ex raise];
+ return NO;
+ }
+ }
+ // Record object in database context
+ if (![new_pkey isEqual:old_pkey]) {
+ NSLog(@"WARNING: (%@) primary key changed from %@ to %@",
+ __PRETTY_FUNCTION__, old_pkey, new_pkey);
+ [databaseContext forgetObject:anObj];
+ }
+
+ [databaseContext recordObject:anObj
+ primaryKey:new_pkey
+ entity:entity
+ snapshot:new_snapshot];
+ [databaseContext recordUpdatedObject:anObj];
+
+ self->updateCount++;
+ [anObj wasUpdatedInChannel:self context:self->databaseContext];
+
+ // Notify delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:didUpdateObject:)])
+ [delegate databaseChannel:self didUpdateObject:anObj];
+
+ [self postNotification:EODatabaseChannelDidUpdateObjectName object:anObj];
+ return YES;
+}
+
+- (BOOL)deleteObject:(id)anObj {
+ // TODO: split this method
+ // TODO: add an deleteObjectX: method which returns an NSException
+ NSException *exception = nil;
+ EOEntity *entity = nil;
+ NSDictionary *pkey = nil;
+ NSDictionary *snapshot = nil;
+ EOSQLQualifier *qualifier = nil;
+
+ [self postNotification:EODatabaseChannelWillDeleteObjectName object:anObj];
+
+ if (![anObj prepareForDeleteInChannel:self context:self->databaseContext])
+ return NO;
+
+ // Check the delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:willDeleteObject:)])
+ anObj = [delegate databaseChannel:self willDeleteObject:anObj];
+
+ // Check nil (delegate disallowes or given object was nil)
+ if (anObj == nil)
+ return NO;
+
+ // Check if fault
+ if ([EOFault isFault:anObj]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Attempt to delete a fault in a database channel"];
+ }
+
+ // Check if we can delete
+ if ([databaseContext updateStrategy] == EONoUpdate) {
+ [self privateReportError:_cmd :
+ @"cannot delete if context has 'NoUpdate' update strategy."];
+ return NO;
+ }
+
+ /* validate object for delete */
+
+ if ((exception = [anObj validateForDelete])) {
+ /* validation failed */
+ [exception raise];
+ }
+
+ // Check if in a transaction
+ if (![databaseContext transactionNestingLevel]) {
+ [self privateReportError:_cmd :
+ @"cannot update if contex has no transaction opened."];
+ return NO;
+ }
+
+ // Get entity
+ entity = [anObj respondsToSelector:@selector(entity)]
+ ? [anObj entity]
+ : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj];
+
+ // Check entity
+ if (entity == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine entity for object %p class %s.",
+ anObj, NSStringFromClass([anObj class])];
+ return NO;
+ }
+ if ([entity isReadOnly]) {
+ [self privateReportError:_cmd :
+ @"cannot delete object %p for readonly entity %@.",
+ anObj, [entity name]];
+ return NO;
+ }
+
+ // Get snapshot and old primary key
+ [databaseContext primaryKey:&pkey andSnapshot:&snapshot forObject:anObj];
+ if (pkey == nil) {
+ if (snapshot == nil)
+ [self privateReportError:_cmd :
+ @"cannot delete object %p because there is no snapshot for it."];
+ pkey = [entity primaryKeyForRow:snapshot];
+ }
+ if (pkey == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine primary key for %p from values %@ entity %@.",
+ anObj, [snapshot description], [entity name]];
+ return NO;
+ }
+
+ // Get and check qualifier for object to delete
+ qualifier = [EOSQLQualifier qualifierForPrimaryKey:pkey entity:entity];
+ if (qualifier == nil) {
+ [self privateReportError:_cmd :
+ @"cannot make qualifier to delete %p primary key %@ entity %@.",
+ anObj, [pkey description], [entity name]];
+ return NO;
+ }
+
+ // Delete adaptor row
+ exception = [adaptorChannel deleteRowsDescribedByQualifierX:qualifier];
+ if (exception != nil) {
+ if (![self _isNoRaiseOnModificationException:exception]) [exception raise];
+ return NO;
+ }
+
+ AUTORELEASE(RETAIN(anObj));
+
+ // Forget object in database context
+ [databaseContext forgetObject:anObj];
+
+ self->deleteCount++;
+ [anObj wasDeletedInChannel:self context:self->databaseContext];
+
+ // Notify delegate
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:didDeleteObject:)])
+ [delegate databaseChannel:self didDeleteObject:anObj];
+
+ [self postNotification:EODatabaseChannelDidDeleteObjectName object:anObj];
+ return YES;
+}
+
+- (BOOL)lockObject:(id)anObj {
+ EOEntity *entity = nil;
+ NSDictionary *pkey = nil;
+ NSDictionary *snapshot = nil;
+ EOSQLQualifier *qualifier = nil;
+
+ [self postNotification:EODatabaseChannelWillLockObjectName object:anObj];
+
+ if (![anObj prepareForLockInChannel:self context:self->databaseContext])
+ return NO;
+
+ // Check the delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:willLockObject:)])
+ anObj = [delegate databaseChannel:self willLockObject:anObj];
+
+ // Check nil (delegate disallowes or given object was nil)
+ if (anObj == nil)
+ return NO;
+
+ // Check if fault
+ if ([EOFault isFault:anObj]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Attempt to lock a fault in a database channel"];
+ }
+
+ // Check if we can lock
+ if ([databaseContext updateStrategy] == EONoUpdate) {
+ [self privateReportError:_cmd :
+ @"cannot lock if context has 'NoUpdate' update strategy."];
+ return NO;
+ }
+
+ // Check if in a transaction
+ if (![databaseContext transactionNestingLevel]) {
+ [self privateReportError:_cmd :
+ @"cannot lock if contex has no transaction opened."];
+ return NO;
+ }
+
+ // Check if fetch is in progress
+ if ([self isFetchInProgress]) {
+ [self privateReportError:_cmd :
+ @"cannot lock if contex has a fetch in progress."];
+ return NO;
+ }
+
+ // Get entity
+ entity = [anObj respondsToSelector:@selector(entity)]
+ ? [anObj entity]
+ : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj];
+
+ // Check entity
+ if (entity == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine entity for object %p class %s.",
+ anObj, NSStringFromClass([anObj class])];
+ return NO;
+ }
+ if ([entity isReadOnly]) {
+ [self privateReportError:_cmd :
+ @"cannot lock object %p for readonly entity %@.",
+ anObj, [entity name]];
+ return NO;
+ }
+
+ // Get snapshot and old primary key
+ [databaseContext primaryKey:&pkey andSnapshot:&snapshot forObject:anObj];
+ if (snapshot == nil) {
+ [self privateReportError:_cmd :
+ @"cannot lock object %p because there is no snapshot for it."];
+ return NO;
+ }
+
+ if (pkey == nil)
+ pkey = [entity primaryKeyForRow:snapshot];
+
+ if (pkey == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine primary key for %p from values %@ entity %@.",
+ anObj, [snapshot description], [entity name]];
+ return NO;
+ }
+
+ {
+ NSArray *lockAttrs = [entity attributesUsedForLocking];
+ NSDictionary *row = nil;
+
+ qualifier = [EOSQLQualifier qualifierForPrimaryKey:pkey entity:entity];
+
+#ifdef DEBUG
+ NSAssert2([lockAttrs count] > 0,
+ @"missing locking attributes: lock=%@ object=%@",
+ lockAttrs, anObj);
+#endif
+ if (![adaptorChannel selectAttributes:lockAttrs
+ describedByQualifier:qualifier
+ fetchOrder:nil
+ lock:YES]) {
+ [self privateReportError:_cmd :
+ @"could not lock %p with qualifier %@.",
+ anObj, [qualifier description]];
+ return NO;
+ }
+ row = [adaptorChannel fetchAttributes:lockAttrs withZone:NULL];
+ [adaptorChannel cancelFetch];
+ if (row == nil) {
+ [self privateReportError:_cmd :
+ @"could not lock %p with qualifier %@.",
+ anObj, [qualifier description]];
+ return NO;
+ }
+ if (![row isEqual:snapshot]) {
+ [self privateReportError:_cmd :
+ @"could not lock %p. Snapshots: self %@ database %@.",
+ anObj, [snapshot description], [row description]];
+ return NO;
+ }
+ }
+
+ // Register lock object in database context
+ [databaseContext recordLockedObject:anObj];
+
+ self->lockCount++;
+ [anObj wasLockedInChannel:self context:self->databaseContext];
+
+ // Notify delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:didLockObject:)])
+ [delegate databaseChannel:self didLockObject:anObj];
+ [self postNotification:EODatabaseChannelDidLockObjectName object:anObj];
+ return YES;
+}
+
+- (BOOL)refetchObject:(id)anObj {
+ EOEntity *entity = nil;
+ NSDictionary *pkey = nil;
+ NSDictionary *snapshot = nil;
+ EOSQLQualifier *qualifier = nil;
+
+ // Check the delegate
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:willRefetchObject:)])
+ anObj = [delegate databaseChannel:self willRefetchObject:anObj];
+
+ // Check nil (delegate disallowes or given object was nil)
+ if (anObj == nil)
+ return NO;
+
+ // Check if fault
+ if ([EOFault isFault:anObj]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Attempt to refetch a fault in a database channel"];
+ }
+
+ // Check if in a transaction
+ if (![databaseContext transactionNestingLevel]) {
+ [self privateReportError:_cmd :
+ @"cannot refetch if context has no transaction opened."];
+ return NO;
+ }
+
+ // Check if fetch is in progress
+ if ([self isFetchInProgress]) {
+ [self privateReportError:_cmd :
+ @"cannot refetch if context has a fetch in progress."];
+ return NO;
+ }
+
+ // Get entity
+ entity = [anObj respondsToSelector:@selector(entity)]
+ ? [anObj entity]
+ : [[[[adaptorChannel adaptorContext] adaptor] model] entityForObject:anObj];
+
+ // Check entity
+ if (entity == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine entity for object %p class %s.",
+ anObj, NSStringFromClass([anObj class])];
+ return NO;
+ }
+
+ // Get snapshot and old primary key
+ [databaseContext primaryKey:&pkey andSnapshot:&snapshot forObject:anObj];
+ if (pkey == nil) {
+ if (snapshot == nil)
+ [self privateReportError:_cmd :
+ @"cannot refetch object %p because there is no snapshot for it."];
+ pkey = [entity primaryKeyForRow:snapshot];
+ }
+ if (pkey == nil) {
+ [self privateReportError:_cmd :
+ @"cannot determine primary key for %p from values %@ entity %@.",
+ anObj, [snapshot description], [entity name]];
+ return NO;
+ }
+
+ // Get and check qualifier for object to refetch
+ qualifier = [EOSQLQualifier qualifierForPrimaryKey:pkey entity:entity];
+ if (qualifier == nil) {
+ [self privateReportError:_cmd :
+ @"cannot make qualifier to refetch %p primary key %@ entity %@.",
+ anObj, [pkey description], [entity name]];
+ return NO;
+ }
+
+ // Request object from adaptor
+ [self setCurrentEntity:entity];
+ [self privateUpdateCurrentEntityInfo];
+ if (currentAttributes == nil) {
+ [self privateReportError:_cmd :
+ @"internal inconsitency while refetching %p.", anObj];
+ return NO;
+ }
+
+#ifdef DEBUG
+ NSAssert3([currentAttributes count] > 0,
+ @"missing attributes for select: lock=%@ object=%@ entity=%@",
+ currentAttributes, anObj, entity);
+#endif
+ if (![adaptorChannel selectAttributes:currentAttributes
+ describedByQualifier:qualifier
+ fetchOrder:nil
+ lock:([databaseContext updateStrategy] ==
+ EOUpdateWithPessimisticLocking)]) {
+ [self privateClearCurrentEntityInfo];
+ return NO;
+ }
+
+ // Get object from adaptor, re-build its faults and record new snapshot
+ anObj = [self privateFetchWithZone:NULL];
+ [self cancelFetch];
+ if (anObj == nil) {
+ [self privateReportError:_cmd :
+ @"could not refetch %p with qualifier %@.",
+ anObj, [qualifier description]];
+ return NO;
+ }
+
+ // Notify delegate
+ if ([delegate respondsToSelector:@selector(databaseChannel:didRefetchObject:)])
+ [delegate databaseChannel:self didRefetchObject:anObj];
+ return YES;
+}
+
+- (id)_createObjectForRow:(NSDictionary*)aRow entity:(EOEntity*)anEntity
+ isPrimaryKey:(BOOL)yn zone:(NSZone*)zone {
+ Class class = Nil;
+ id anObj = nil;
+
+ if (anEntity == nil)
+ return nil;
+
+ class = [self privateClassForEntity:anEntity];
+
+ // Create new instance
+ if ([class respondsToSelector:@selector(classForEntity:values:)])
+ class = [class classForEntity:anEntity values:aRow];
+
+ anObj = [class allocWithZone:zone];
+
+ return anObj;
+}
+
+- (id)allocateObjectForRow:(NSDictionary *)row entity:(EOEntity *)anEntity
+ zone:(NSZone *)zone {
+
+ Class class = Nil;
+ id anObj = nil;
+
+ if (anEntity == nil)
+ return nil;
+
+ class = [self privateClassForEntity:anEntity];
+
+ // Create new instance
+ if ([class respondsToSelector:@selector(classForEntity:values:)])
+ class = [class classForEntity:anEntity values:row];
+
+ anObj = [class allocWithZone:zone];
+
+ return anObj;
+}
+
+- (id)initializedObjectForRow:(NSDictionary *)row
+ entity:(EOEntity *)anEntity
+ zone:(NSZone *)zone
+{
+ id anObj;
+
+ anObj = [self allocateObjectForRow:row entity:anEntity zone:zone];
+
+ anObj = [anObj respondsToSelector:@selector(initWithPrimaryKey:entity:)]
+ ? [anObj initWithPrimaryKey:row entity:anEntity]
+ : [anObj init];
+
+ return AUTORELEASE(anObj);
+}
+
+/*
+ * Fetching objects
+ */
+
+- (id)_fetchObject:(id)anObj qualifier:(EOSQLQualifier *)qualifier {
+ id obj;
+
+ [self selectObjectsDescribedByQualifier:qualifier fetchOrder:nil];
+ obj = [self fetchWithZone:NULL];
+ [self cancelFetch];
+ return obj;
+}
+
+- (BOOL)selectObjectsDescribedByQualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+{
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:willSelectObjectsDescribedByQualifier:fetchOrder:)])
+ if (![delegate databaseChannel:self
+ willSelectObjectsDescribedByQualifier:qualifier
+ fetchOrder:fetchOrder])
+ return NO;
+
+ [self setCurrentEntity:[qualifier entity]];
+ [self privateUpdateCurrentEntityInfo];
+ if (self->currentAttributes == nil) {
+ [self privateReportError:_cmd :
+ @"internal inconsitency while selecting."];
+ }
+#ifdef DEBUG
+ NSAssert3([self->currentAttributes count] > 0,
+ @"missing select attributes: attrs=%@, qualifier=%@, entity=%@",
+ self->currentAttributes, qualifier, self->currentEntity);
+#endif
+ if (![adaptorChannel selectAttributes:self->currentAttributes
+ describedByQualifier:qualifier
+ fetchOrder:fetchOrder
+ lock:([databaseContext updateStrategy] ==
+ EOUpdateWithPessimisticLocking)]) {
+ [self privateClearCurrentEntityInfo];
+ [self privateReportError:_cmd :
+ @"could not select attributes with qualifier %@.",
+ [qualifier description]];
+ return NO;
+ }
+
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:didSelectObjectsDescribedByQualifier:fetchOrder:)])
+ [delegate databaseChannel:self
+ didSelectObjectsDescribedByQualifier:qualifier
+ fetchOrder:fetchOrder];
+ return YES;
+}
+
+- (id)fetchWithZone:(NSZone *)zone {
+ id object = nil;
+
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:willFetchObjectOfClass:withZone:)]) {
+ Class class;
+
+ class = currentClass
+ ? currentClass
+ : [self privateClassForEntity:currentEntity];
+
+ [delegate databaseChannel:self
+ willFetchObjectOfClass:class
+ withZone:zone];
+ }
+ object = [self privateFetchWithZone:zone];
+ if (object == nil)
+ return nil;
+
+ if ([delegate respondsToSelector:@selector(databaseChannel:didFetchObject:)])
+ [delegate databaseChannel:self didFetchObject:object];
+
+ return object;
+}
+
+- (BOOL)isFetchInProgress {
+ return [[self adaptorChannel] isFetchInProgress];
+}
+
+- (void)cancelFetch {
+ if ([[self adaptorChannel] isFetchInProgress]) {
+ [self privateClearCurrentEntityInfo];
+ [[self adaptorChannel] cancelFetch];
+ }
+}
+
+- (void)setCurrentEntity:(EOEntity *)_entity {
+ // Clear entity info
+ [self privateClearCurrentEntityInfo];
+ // Set new entity
+ NSAssert(self->currentEntity == nil, @"entity not cleared correctly ..");
+ self->currentEntity = RETAIN(_entity);
+}
+
+- (void)privateClearCurrentEntityInfo {
+ RELEASE(self->currentEntity); self->currentEntity = nil;
+ RELEASE(self->currentAttributes); self->currentAttributes = nil;
+ RELEASE(self->currentRelations); self->currentRelations = nil;
+ self->currentClass = Nil;
+ self->currentReady = NO;
+}
+
+- (void)privateUpdateCurrentEntityInfo {
+ if (self->currentEntity == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Must use setCurrentEntity if select is not done "
+ @"through database"];
+ }
+
+ if (self->currentAttributes == nil)
+ self->currentAttributes =
+ RETAIN([self->currentEntity attributesUsedForFetch]);
+ if (self->currentRelations == nil)
+ self->currentRelations = RETAIN([self->currentEntity relationsUsedForFetch]);
+ self->currentReady = YES;
+}
+
+/*
+ * Private methods
+ */
+
+- (Class)privateClassForEntity:(EOEntity *)anEntity {
+ Class class;
+
+ if (anEntity == currentEntity && currentClass)
+ return currentClass;
+
+ // Get class for new object
+ class = NSClassFromString([anEntity className]);
+
+ if (!class && [delegate respondsToSelector:
+ @selector(databaseChannel:failedToLookupClassNamed:)])
+ class = [delegate databaseChannel:self
+ failedToLookupClassNamed:[[anEntity className] cString]];
+ if (class == Nil)
+ class = [EOGenericRecord class];
+
+ if (anEntity == currentEntity)
+ currentClass = class;
+
+ return class;
+}
+
+- (id)privateFetchWithZone:(NSZone *)_zone {
+ NSMutableDictionary *values = nil;
+ id object = nil;
+ NSDictionary *pkey = nil;
+ NSDictionary *snapshot = nil;
+ NSDictionary *row = nil;
+ NSDictionary *dict = nil;;
+
+ // Be sure we have entity info (raises if no entity is set)
+ if (!self->currentReady)
+ [self privateUpdateCurrentEntityInfo];
+
+ // fetch row from adaptor
+ row = [[self adaptorChannel] fetchAttributes:self->currentAttributes
+ withZone:_zone];
+ if (row == nil)
+ // Results set finished or no more result sets
+ return nil;
+#if 0
+ row = [row copyWithZone:_zone];
+ AUTORELEASE(row);
+#endif
+
+ // determine primary key and snapshot
+ snapshot = [self->currentEntity snapshotForRow:row];
+ pkey = [self->currentEntity primaryKeyForRow:row];
+
+ if ((pkey == nil) || (snapshot == nil)) {
+ // TODO - should we have a delegate method here ?
+ [NSException raise:NSInvalidArgumentException
+ format:@"Cannot determine primary key and snapshot for row"];
+ }
+
+ // lookup object in context/database
+ object = [self->databaseContext objectForPrimaryKey:pkey
+ entity:currentEntity];
+
+ // use old, make new, clear fault
+ if (object == nil) {
+ //NSLog(@"new anObj\n");
+ object = [self initializedObjectForRow:row
+ entity:currentEntity
+ zone:_zone];
+ }
+ if ([EOFault isFault:object]) {
+ [EODatabaseFault clearFault:object];
+
+ object = [object respondsToSelector:@selector(initWithPrimaryKey:entity:)]
+ ? [object initWithPrimaryKey:row entity:currentEntity]
+ : [object init];
+
+ if (object == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"could not initialize cleared fault with "
+ @"row `%@' and entity %@",
+ [row description], [currentEntity name]];
+ }
+ }
+
+ // make values
+ // TODO - handle only class properties to object
+ values = [NSMutableDictionary dictionaryWithCapacity:
+ ([row count] + [currentRelations count])];
+ [values addEntriesFromDictionary:row];
+
+ // resolve relationships (to-one and to-many)
+ {
+ EORelationship *rel = nil;
+ int i, n = [self->currentRelations count];
+ id fault = nil;
+
+ for (i = 0; i < n; i++) {
+ rel = [self->currentRelations objectAtIndex:i];
+
+ // Check if the delegate can provide a different relationship
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:relationshipForRow:relationship:)]) {
+ id nrel = [delegate databaseChannel:self
+ relationshipForRow:row
+ relationship:rel];
+ rel = nrel ? nrel : rel;
+ }
+ if ([rel isToMany]) {
+ // Build to-many fault
+ EOSQLQualifier* qualifier =
+ [EOSQLQualifier qualifierForRow:row relationship:rel];
+
+ if (qualifier == nil) {
+ // HH: THROW was uncommented ..
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"Cannot build fault qualifier for relationship"];
+ // TODO
+ continue;
+ }
+
+#if LIB_FOUNDATION_LIBRARY
+ if ([NSClassFromString([[rel destinationEntity] className])
+ isGarbageCollectable])
+ fault = [EODatabaseFault gcArrayFaultWithQualifier:qualifier
+ fetchOrder:nil
+ databaseChannel:self
+ zone:_zone];
+ else
+#endif
+ fault = [EODatabaseFault arrayFaultWithQualifier:qualifier
+ fetchOrder:nil
+ databaseChannel:self
+ zone:_zone];
+ }
+ else {
+ // Build to-one fault
+ EOEntity *faultEntity;
+ NSDictionary *faultKey;
+
+ faultEntity = [rel destinationEntity];
+ faultKey = [rel foreignKeyForRow:row];
+ faultKey = [faultEntity primaryKeyForRow:faultKey];
+
+ if (faultEntity == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Cannot get entity for relationship"];
+ }
+
+ if (faultKey) {
+ fault = [self->databaseContext objectForPrimaryKey:faultKey
+ entity:faultEntity];
+ if (fault == nil) {
+ fault = [EODatabaseFault objectFaultWithPrimaryKey:faultKey
+ entity:faultEntity
+ databaseChannel:self
+ zone:_zone];
+ [databaseContext recordObject:fault
+ primaryKey:faultKey
+ entity:faultEntity
+ snapshot:nil];
+ }
+ }
+ else
+ fault = [EONull null];
+ }
+
+ if (fault)
+ [values setObject:fault forKey:[rel name]];
+ }
+ }
+
+ // check if is updated in another context or just updated or new (delegate)
+ dict = values;
+ if ([[databaseContext database] isObject:object
+ updatedOutsideContext:databaseContext]) {
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:willRefetchConflictingObject:withSnapshot:)]) {
+ dict = [delegate databaseChannel:self
+ willRefetchConflictingObject:object
+ withSnapshot:values];
+ }
+ else {
+ [NSException raise:NSInvalidArgumentException
+ format:@"object updated in an uncommitted transaction "
+ @"was fetched"];
+ }
+ }
+ else {
+ if ([delegate respondsToSelector:
+ @selector(databaseChannel:willRefetchObject:fromSnapshot:)]) {
+ dict = [delegate databaseChannel:self
+ willRefetchObject:object
+ fromSnapshot:values];
+ }
+ }
+ // does delegate disallow setting the new values and recording the fetch ?
+ if (dict == nil)
+ return object;
+
+ // put values
+ [object takeValuesFromDictionary:dict];
+
+ // register lock if locked
+ if ([databaseContext updateStrategy] == EOUpdateWithPessimisticLocking)
+ [databaseContext recordLockedObject:object];
+
+ // register object in context
+ [databaseContext recordObject:object
+ primaryKey:pkey
+ entity:currentEntity
+ snapshot:snapshot];
+
+ // awake object from database channel
+ if ([object respondsToSelector:@selector(awakeForDatabaseChannel:)])
+ [object awakeForDatabaseChannel:self];
+
+ // Done.
+ return object;
+}
+
+// ******************** Reporting errors ********************
+
+- (void)privateReportError:(SEL)method :(NSString*)format,... {
+ NSString* message;
+ va_list va;
+
+ if (![[databaseContext database] logsErrorMessages])
+ return;
+
+ va_start(va, format);
+ message = AUTORELEASE([[NSString alloc] initWithFormat:format arguments:va]);
+ va_end(va);
+
+ [[databaseContext database]
+ reportErrorFormat:
+ @"EODatabaseChannel:error in [EODatabaseChannel %@]: %@",
+ NSStringFromSelector(method), message];
+}
+
+@end /* EODatabaseChannel */
+
+@implementation NSObject(EODatabaseChannelEONotifications)
+
+- (BOOL)prepareForDeleteInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+ return YES;
+}
+- (void)wasDeletedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+}
+
+- (BOOL)prepareForInsertInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+ return YES;
+}
+- (void)wasInsertedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+}
+
+- (BOOL)prepareForUpdateInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+ return YES;
+}
+- (void)wasUpdatedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+}
+
+- (BOOL)prepareForLockInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+ return YES;
+}
+- (void)wasLockedInChannel:(EODatabaseChannel *)_channel
+ context:(EODatabaseContext *)_ctx
+{
+}
+
+@end /* NSObject(EODatabaseChannelNotifications) */
+
+@implementation EODatabaseChannel(Statistics)
+
+- (unsigned int)successfulOpenCount {
+ return self->successfulOpenCount;
+}
+
+- (unsigned int)failedOpenCount {
+ return self->failedOpenCount;
+}
+
+- (unsigned int)closeCount {
+ return self->closeCount;
+}
+
+- (unsigned int)insertCount {
+ return self->insertCount;
+}
+
+- (unsigned int)updateCount {
+ return self->updateCount;
+}
+
+- (unsigned int)deleteCount {
+ return self->deleteCount;
+}
+
+- (unsigned int)lockCount {
+ return self->lockCount;
+}
+
+@end
--- /dev/null
+/*
+ EODatabaseContext.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ Author: Helge Hess <helge.hess@mdlink.de>
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EODatabaseContext.h"
+#import "EOAdaptor.h"
+#import "EOAdaptorContext.h"
+#import "EODatabase.h"
+#import "EODatabaseChannel.h"
+#import "EOEntity.h"
+#import "EODatabaseFault.h"
+#import "EOGenericRecord.h"
+#import "EOModel.h"
+#import "EOObjectUniquer.h"
+#include "EOModelGroup.h"
+#include <EOControl/EOFetchSpecification.h>
+#include <EOControl/EOKeyGlobalID.h>
+
+NSString *EODatabaseContextWillBeginTransactionName =
+ @"EODatabaseContextWillBeginTransaction";
+NSString *EODatabaseContextDidBeginTransactionName =
+ @"EODatabaseContextDidBeginTransaction";
+NSString *EODatabaseContextWillRollbackTransactionName =
+ @"EODatabaseContextWillRollbackTransaction";
+NSString *EODatabaseContextDidRollbackTransactionName =
+ @"EODatabaseContextDidRollbackTransaction";
+NSString *EODatabaseContextWillCommitTransactionName =
+ @"EODatabaseContextWillCommitTransaction";
+NSString *EODatabaseContextDidCommitTransactionName =
+ @"EODatabaseContextDidCommitTransaction";
+
+struct EODatabaseContextModificationQueue {
+ struct EODatabaseContextModificationQueue *next;
+ enum {
+ update,
+ delete,
+ insert
+ } op;
+ id object;
+};
+
+/*
+ * Transaction scope
+ */
+
+typedef struct _EOTransactionScope {
+ struct _EOTransactionScope *previous;
+ EOObjectUniquer *objectsDictionary;
+ NSMutableArray *objectsUpdated;
+ NSMutableArray *objectsDeleted;
+ NSMutableArray *objectsLocked;
+} EOTransactionScope;
+
+static inline EOTransactionScope *_newTxScope(NSZone *_zone) {
+ EOTransactionScope *newScope;
+
+ newScope = NSZoneMalloc(_zone, sizeof(EOTransactionScope));
+ newScope->objectsDictionary = [[EOObjectUniquer allocWithZone:_zone] init];
+ newScope->objectsUpdated = [[NSMutableArray allocWithZone:_zone] init];
+ newScope->objectsDeleted = [[NSMutableArray allocWithZone:_zone] init];
+ newScope->objectsLocked = [[NSMutableArray allocWithZone:_zone] init];
+
+ return newScope;
+}
+static inline void _freeTxScope(NSZone *_zone, EOTransactionScope *_txScope) {
+ RELEASE(_txScope->objectsDictionary); _txScope->objectsDictionary = nil;
+ RELEASE(_txScope->objectsUpdated); _txScope->objectsUpdated = nil;
+ RELEASE(_txScope->objectsDeleted); _txScope->objectsDeleted = nil;
+ RELEASE(_txScope->objectsLocked); _txScope->objectsLocked = nil;
+ NSZoneFree(_zone, _txScope); _txScope = NULL;
+}
+
+@implementation EODatabaseContext
+
+#if 0 // no such callback!
++ (void)initialize {
+ static BOOL isInitialized = NO;
+ if (!isInitialized) {
+ isInitialized = YES;
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(_objectStoreNeeded:)
+ name:@"EOCooperatingObjectStoreNeeded"
+ object:nil];
+ }
+}
+#endif
+
+static inline void _checkTxInProgress(EODatabaseContext *self,
+ const char *_function)
+{
+ if (self->transactionNestingLevel == 0) {
+ [NSException raise:NSInternalInconsistencyException
+ format:
+ @"EODatabaseContext:%x: No transaction in progress "
+ @"in %s", self, _function];
+ }
+}
+
+// init
+
+- (id)initWithDatabase:(EODatabase *)aDatabase {
+ static int reuseAdaptorCtx = -1;
+ if (reuseAdaptorCtx == -1) {
+ reuseAdaptorCtx = [[[NSUserDefaults standardUserDefaults]
+ objectForKey:@"EOReuseAdaptorContext"]
+ boolValue] ? 1 : 0;
+ }
+ if (reuseAdaptorCtx) {
+ NSEnumerator *contexts;
+ EOAdaptorContext *actx;
+
+ contexts = [[[aDatabase adaptor] contexts] objectEnumerator];
+ while ((actx = [contexts nextObject])) {
+ if (![actx hasOpenTransaction]) {
+#if DEBUG
+ NSLog(@"reuse adaptor context: %@", actx);
+#endif
+ self->adaptorContext = actx;
+ break;
+ }
+ }
+ if (self->adaptorContext == nil)
+ self->adaptorContext = [[aDatabase adaptor] createAdaptorContext];
+ }
+ else
+ self->adaptorContext = [[aDatabase adaptor] createAdaptorContext];
+
+ if ((aDatabase == nil) || (adaptorContext == nil)) {
+ NSLog(@"EODatabaseContext could not create adaptor context");
+ AUTORELEASE(self);
+ return nil;
+ }
+ RETAIN(self->adaptorContext);
+
+ self->database = RETAIN(aDatabase);
+ self->channels = [[NSMutableArray allocWithZone:[self zone]] init];
+ self->transactionStackTop = NULL;
+ self->transactionNestingLevel = 0;
+ self->updateStrategy = EOUpdateWithOptimisticLocking;
+ self->isKeepingSnapshots = YES;
+ self->isUniquingObjects = [self->database uniquesObjects];
+
+ [database contextDidInit:self];
+ return self;
+}
+
+- (void)dealloc {
+ [database contextWillDealloc:self];
+
+ if (self->ops) {
+ struct EODatabaseContextModificationQueue *q;
+
+ while ((q = self->ops)) {
+ self->ops = q->next;
+ RELEASE(q->object);
+ free(q);
+ }
+ }
+
+ while (self->transactionNestingLevel) {
+ if (![self rollbackTransaction])
+ break;
+ }
+ while (self->transactionStackTop)
+ [self privateRollbackTransaction];
+
+ RELEASE(self->adaptorContext); self->adaptorContext = nil;
+ RELEASE(self->database); self->database = nil;
+ RELEASE(self->channels); self->channels = nil;
+ [super dealloc];
+}
+
+/* accessors */
+
+- (void)setDelegate:(id)_delegate {
+ self->delegate = _delegate;
+}
+- (id)delegate {
+ return self->delegate;
+}
+
+- (EODatabase *)database {
+ return self->database;
+}
+
+- (EOAdaptorContext *)adaptorContext {
+ return self->adaptorContext;
+}
+
+// channels
+
+- (BOOL)hasBusyChannels {
+ int i;
+
+ for (i = [channels count]-1; i >= 0; i--) {
+ if ([[[channels objectAtIndex:i] nonretainedObjectValue]
+ isFetchInProgress])
+ return YES;
+ }
+ return NO;
+}
+
+- (BOOL)hasOpenChannels {
+ int i;
+
+ for (i = [channels count]-1; i >= 0; i--) {
+ if ([[[channels objectAtIndex:i] nonretainedObjectValue] isOpen])
+ return YES;
+ }
+ return NO;
+}
+
+- (NSArray *)channels {
+ return [self registeredChannels];
+}
+
+- (id)createChannel {
+ return AUTORELEASE([[EODatabaseChannel alloc] initWithDatabaseContext:self]);
+}
+
+- (void)channelDidInit:(id)aChannel {
+ [self registerChannel:aChannel];
+}
+
+- (void)channelWillDealloc:(id)aChannel {
+ [self unregisterChannel:aChannel];
+}
+
+/*
+ * Controlling transactions
+ */
+
+- (BOOL)beginTransaction {
+ NSNotificationCenter *nc;
+
+ if ([adaptorContext transactionNestingLevel] !=
+ (unsigned)transactionNestingLevel) {
+ [NSException raise:NSInternalInconsistencyException
+ format:
+ @"EODatabaseContext:%x:transaction nesting levels do not match: "
+ @"database has %d, adaptor has %d, "
+ @"in [EODatabaseContext beginTransaction]",
+ self, transactionNestingLevel,
+ [adaptorContext transactionNestingLevel]];
+ }
+
+ nc = [NSNotificationCenter defaultCenter];
+
+ [nc postNotificationName:EODatabaseContextWillBeginTransactionName
+ object:self];
+
+ if (![self->adaptorContext beginTransaction])
+ return NO;
+ [self privateBeginTransaction];
+
+ txBeginCount++;
+ [nc postNotificationName:EODatabaseContextDidBeginTransactionName
+ object:self];
+ return YES;
+}
+
+- (BOOL)commitTransaction {
+ NSNotificationCenter *nc;
+
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+
+ if ([adaptorContext transactionNestingLevel] !=
+ (unsigned)self->transactionNestingLevel) {
+ [NSException raise:NSInternalInconsistencyException
+ format:
+ @"EODatabaseContext:%x:transaction nesting levels do not match: "
+ @"database has %d, adaptor has %d, "
+ @"in [EODatabaseContext commitTransaction]",
+ self, transactionNestingLevel,
+ [adaptorContext transactionNestingLevel]];
+ }
+
+ nc = [NSNotificationCenter defaultCenter];
+ [nc postNotificationName:EODatabaseContextWillCommitTransactionName
+ object:self];
+
+ if (![adaptorContext commitTransaction])
+ return NO;
+ [self privateCommitTransaction];
+
+ self->txCommitCount++;
+ [nc postNotificationName:EODatabaseContextDidCommitTransactionName
+ object:self];
+ return YES;
+}
+
+- (BOOL)rollbackTransaction {
+ NSNotificationCenter *nc;
+
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+
+ if ([self->adaptorContext transactionNestingLevel] !=
+ (unsigned)self->transactionNestingLevel) {
+ [NSException raise:NSInternalInconsistencyException
+ format:
+ @"EODatabaseContext:%x:transaction nesting levels do not match: "
+ @"database has %d, adaptor has %d, "
+ @"in [EODatabaseContext rollbackTransaction]",
+ self, transactionNestingLevel,
+ [adaptorContext transactionNestingLevel]];
+ }
+
+ nc = [NSNotificationCenter defaultCenter];
+ [nc postNotificationName:EODatabaseContextWillRollbackTransactionName
+ object:self];
+
+ if (![self->adaptorContext rollbackTransaction])
+ return NO;
+ [self privateRollbackTransaction];
+
+ self->txRollbackCount++;
+ [nc postNotificationName:EODatabaseContextDidRollbackTransactionName
+ object:self];
+ return YES;
+}
+
+
+// ******************** notifications ********************
+
+- (void)transactionDidBegin {
+ [self->adaptorContext transactionDidBegin];
+ [self privateBeginTransaction];
+}
+
+- (void)transactionDidCommit {
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+ [self->adaptorContext transactionDidCommit];
+ [self privateCommitTransaction];
+}
+
+- (void)transactionDidRollback {
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+ [adaptorContext transactionDidRollback];
+ [self privateRollbackTransaction];
+}
+
+/*
+ * Nesting transactions
+ */
+
+- (BOOL)canNestTransactions {
+ return [adaptorContext canNestTransactions];
+}
+- (unsigned)transactionNestingLevel {
+ return transactionNestingLevel;
+}
+
+/*
+ * Setting the update strategy
+ */
+
+- (void)setUpdateStrategy:(EOUpdateStrategy)aStrategy {
+ if ([self transactionNestingLevel]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot change update strategy "
+ @"when context has a transaction open, "
+ @"in [EODatabaseContext setUpdateStrategy]",
+ self];
+ }
+ updateStrategy = aStrategy;
+ isKeepingSnapshots = (updateStrategy == EOUpdateWithNoLocking) ? NO : YES;
+ isUniquingObjects = [database uniquesObjects];
+}
+
+- (EOUpdateStrategy)updateStrategy {
+ return self->updateStrategy;
+}
+
+- (BOOL)keepsSnapshots {
+ return self->isKeepingSnapshots;
+}
+
+/*
+ * Processing transactions internally
+ */
+
+- (void)privateBeginTransaction {
+ EOTransactionScope *newScope = NULL;
+
+ newScope = _newTxScope([self zone]);
+ newScope->previous = transactionNestingLevel ? transactionStackTop : NULL;
+ transactionStackTop = newScope;
+ transactionNestingLevel++;
+
+ if (transactionNestingLevel == 1)
+ self->isUniquingObjects = [database uniquesObjects];
+}
+
+- (void)privateCommitTransaction {
+ EOTransactionScope *newScope = transactionStackTop;
+
+ transactionStackTop = newScope->previous;
+ transactionNestingLevel--;
+
+ // In nested transaction fold updated and deleted objects
+ // into the parent transaction; locked objects are forgotten
+ // deleted objects are deleted form the parent transaction
+ if (transactionNestingLevel) {
+ // Keep updated objects
+ [transactionStackTop->objectsUpdated
+ addObjectsFromArray:newScope->objectsUpdated];
+ // Keep deleted objects
+ [transactionStackTop->objectsDeleted
+ addObjectsFromArray:newScope->objectsDeleted];
+ // Register objects in parent transaction scope
+ [newScope->objectsDictionary
+ transferTo:transactionStackTop->objectsDictionary
+ objects:YES andSnapshots:YES];
+ }
+ // If this was the first transaction then fold the changes
+ // into the database; locked and updateted objects are forgotten
+ else {
+ int i, n;
+
+ for (i = 0, n = [newScope->objectsDeleted count]; i < n; i++)
+ [database forgetObject:[newScope->objectsDeleted objectAtIndex:i]];
+
+ // Register objects into the database
+ if (self->isUniquingObjects || [database keepsSnapshots]) {
+ [newScope->objectsDictionary transferTo:[database objectUniquer]
+ objects:self->isUniquingObjects
+ andSnapshots:[database keepsSnapshots]];
+ }
+ }
+
+ // Kill transaction scope
+ _freeTxScope([self zone], newScope);
+}
+
+- (void)privateRollbackTransaction {
+ EOTransactionScope *newScope = transactionStackTop;
+
+ transactionStackTop = newScope->previous;
+ transactionNestingLevel--;
+
+ // Forget snapshots, updated, deleted and locked objects
+ // in current transaction
+
+ // Kill transaction scope
+ _freeTxScope([self zone], newScope);
+}
+
+// Handle Objects
+
+- (void)forgetObject:(id)_object {
+ EOTransactionScope *scope = NULL;
+
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+
+ if (_object == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot forget null object, "
+ @"in [EODatabaseContext forgetObject]",
+ self];
+ }
+ if ([EOFault isFault:_object]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot forget forget a fault object, "
+ @"in [EODatabaseContext forgetObject]",
+ self];
+ }
+
+ [transactionStackTop->objectsDeleted addObject:_object];
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ [scope->objectsDictionary forgetObject:_object];
+ }
+}
+
+- (id)objectForPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity {
+ EOTransactionScope *scope = NULL;
+ id _object = nil;
+
+ if (!self->isUniquingObjects || (_key == nil) || (_entity == nil))
+ return nil;
+
+ _key = [_entity primaryKeyForRow:_key];
+ if (_key == nil) return nil;
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ _object = [scope->objectsDictionary objectForPrimaryKey:_key
+ entity:_entity];
+ if (_object)
+ return _object;
+ }
+
+ return [self->database objectForPrimaryKey:_key entity:_entity];
+}
+
+- (void)recordObject:(id)_object
+ primaryKey:(NSDictionary *)_key
+ entity:(EOEntity *)_entity
+ snapshot:(NSDictionary *)snapshot
+{
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+
+ if (_object == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record null object, "
+ @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+ if ((_entity == nil) && self->isUniquingObjects) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record object with null entity "
+ @"when uniquing objects, "
+ @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+
+ _key = [_entity primaryKeyForRow:_key];
+
+ if ((_key == nil) && self->isUniquingObjects) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record object with null key "
+ @"when uniquing objects, "
+ @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]",
+ self];
+ }
+ if ((snapshot == nil) && isKeepingSnapshots && ![EOFault isFault:_object]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record object with null snapshot "
+ @"when keeping snapshots, "
+ @"in [EODatabaseContext recordObject:primaryKey:entity:snapshot:]"
+ @": snapshot=%s keepsSnapshots=%s isFault=%s",
+ self,
+ snapshot ? "yes" : "no",
+ isKeepingSnapshots ? "yes" : "no",
+ [EOFault isFault:_object] ? "yes" : "no"];
+ }
+
+ if (self->isKeepingSnapshots || self->isUniquingObjects) {
+ EOObjectUniquer *cache = transactionStackTop->objectsDictionary;
+
+ [cache recordObject:_object
+ primaryKey: self->isUniquingObjects ? _key : nil
+ entity: self->isUniquingObjects ? _entity : nil
+ snapshot: self->isKeepingSnapshots ? snapshot : nil];
+ }
+}
+
+- (void)recordObject:(id)_object
+ primaryKey:(NSDictionary *)_key
+ snapshot:(NSDictionary *)_snapshot
+{
+ EOEntity *entity = nil;
+
+ entity = [_object respondsToSelector:@selector(entity)]
+ ? [_object entity]
+ : [[[database adaptor] model] entityForObject:_object];
+
+ [self recordObject:_object primaryKey:_key entity:entity snapshot:_snapshot];
+}
+
+- (NSDictionary *)snapshotForObject:(id)_object {
+ EOTransactionScope *scope = NULL;
+ EOUniquerRecord *rec = NULL;
+
+ if (!isKeepingSnapshots)
+ return nil;
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ rec = [scope->objectsDictionary recordForObject:_object];
+ if (rec)
+ return rec->snapshot;
+ }
+
+ rec = [[self->database objectUniquer] recordForObject:_object];
+ if (rec) return rec->snapshot;
+
+ return nil;
+}
+
+- (NSDictionary*)primaryKeyForObject:(id)_object {
+ EOTransactionScope *scope = NULL;
+ EOUniquerRecord *rec = NULL;
+
+ if ([self->database uniquesObjects])
+ return nil;
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ rec = [scope->objectsDictionary recordForObject:_object];
+ if (rec) return rec->pkey;
+ }
+
+ rec = [[self->database objectUniquer] recordForObject:_object];
+ if (rec) return rec->pkey;
+ return nil;
+}
+
+- (void)primaryKey:(NSDictionary **)_key
+ andSnapshot:(NSDictionary **)_snapshot
+ forObject:_object
+{
+ EOTransactionScope *scope = NULL;
+ EOUniquerRecord *rec = NULL;
+
+ if (!self->isKeepingSnapshots && ![self->database uniquesObjects]) {
+ *_key = *_snapshot = nil;
+ return;
+ }
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ rec = [scope->objectsDictionary recordForObject:_object];
+ if (rec) {
+ if (_key) *_key = rec->pkey;
+ if (_snapshot) *_snapshot = rec->snapshot;
+ return;
+ }
+ }
+
+ rec = [[self->database objectUniquer] recordForObject:_object];
+ if (rec) {
+ if (_key) *_key = rec->pkey;
+ if (_snapshot) *_snapshot = rec->snapshot;
+ return;
+ }
+
+ if (_key) *_key = nil;
+ if (_snapshot) *_snapshot = nil;
+}
+
+- (void)recordLockedObject:(id)_object {
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+
+ if (_object == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record null object as locked, "
+ @"in [EODatabaseContext recordLockedObject:]",
+ self];
+ }
+ if ([EOFault isFault:_object]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record a fault object as locked, "
+ @"in [EODatabaseContext recordLockedObject:]",
+ self];
+ }
+ [transactionStackTop->objectsLocked addObject:_object];
+}
+
+- (BOOL)isObjectLocked:(id)_object {
+ EOTransactionScope *scope;
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ if ([scope->objectsLocked indexOfObjectIdenticalTo:_object]!=NSNotFound)
+ return YES;
+ }
+ return NO;
+}
+
+- (void)recordUpdatedObject:(id)_object {
+ _checkTxInProgress(self, __PRETTY_FUNCTION__);
+
+ if (_object == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record null object as updatetd, "
+ @"in [EODatabaseContext recordUpdatedObject:]",
+ self];
+ }
+ if ([EOFault isFault:_object]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EODatabaseContext:%x: Cannot record fault object as updated, "
+ @"in [EODatabaseContext recordUpdatedObject:]",
+ self];
+ }
+
+ [transactionStackTop->objectsUpdated addObject:_object];
+}
+
+- (BOOL)isObjectUpdated:(id)_object {
+ EOTransactionScope *scope;
+
+ for (scope = transactionStackTop; scope; scope = scope->previous) {
+ if ([scope->objectsUpdated indexOfObjectIdenticalTo:_object] != NSNotFound)
+ return YES;
+ if ([scope->objectsDeleted indexOfObjectIdenticalTo:_object] != NSNotFound)
+ return YES;
+ }
+ return NO;
+}
+
+/* description */
+
+- (NSString *)description {
+ return [NSString stringWithFormat:
+ @"<%@[0x%08X]: #channels=%i tx-nesting=%i>",
+ NSStringFromClass([self class]), self,
+ [self->channels count],
+ [self transactionNestingLevel]];
+}
+
+@end /* EODatabaseContext */
+
+@implementation EODatabaseContext(Statistics)
+
+- (unsigned int)transactionBeginCount {
+ return self->txBeginCount;
+}
+- (unsigned int)transactionCommitCount {
+ return self->txCommitCount;
+}
+- (unsigned int)transactionRollbackCount {
+ return self->txRollbackCount;
+}
+
+@end /* EODatabaseContext(Statistics) */
+
+@implementation EODatabaseContext(NewInEOF2)
+
+// THREAD
+static Class EODatabaseContextClass = Nil;
+
++ (void)setContextClassToRegister:(Class)_cclass {
+ EODatabaseContextClass = _cclass;
+}
++ (Class)contextClassToRegister {
+ return EODatabaseContextClass ? EODatabaseContextClass : self;
+}
+
+- (EODatabaseChannel *)availableChannel {
+ int i;
+
+ for (i = [self->channels count] - 1; i >= 0; i--) {
+ EODatabaseChannel *channel;
+
+ channel = [[self->channels objectAtIndex:i] nonretainedObjectValue];
+ if (![channel isFetchInProgress])
+ return channel;
+ }
+
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:@"EODatabaseChannelNeeded"
+ object:self];
+
+ /* recheck for channel */
+
+ for (i = [self->channels count] - 1; i >= 0; i--) {
+ EODatabaseChannel *channel;
+
+ channel = [[self->channels objectAtIndex:i] nonretainedObjectValue];
+ if (![channel isFetchInProgress])
+ return channel;
+ }
+
+ return nil;
+}
+
+- (NSArray *)registeredChannels {
+ NSMutableArray *array;
+ int i, n;
+
+ array = [NSMutableArray array];
+ for (i=0, n=[channels count]; i < n; i++) {
+ EODatabaseChannel *channel =
+ [[channels objectAtIndex:i] nonretainedObjectValue];
+
+ [array addObject:channel];
+ }
+
+ return array;
+}
+- (void)registerChannel:(EODatabaseChannel *)_channel {
+ [self->channels addObject:[NSValue valueWithNonretainedObject:_channel]];
+}
+- (void)unregisterChannel:(EODatabaseChannel *)_channel {
+ int i;
+
+ for (i = [self->channels count] - 1; i >= 0; i--) {
+ EODatabaseChannel *channel;
+
+ channel = [[self->channels objectAtIndex:i] nonretainedObjectValue];
+
+ if (channel == _channel) {
+ [channels removeObjectAtIndex:i];
+ break;
+ }
+ }
+}
+
+/* cooperating object store */
+
+- (void)commitChanges {
+ [self commitTransaction];
+}
+- (void)rollbackChanges {
+ [self rollbackTransaction];
+}
+
+- (void)performChanges {
+ [self notImplemented:_cmd];
+}
+
+/* store specific properties */
+
+- (NSDictionary *)valuesForKeys:(NSArray *)_keys object:(id)_object {
+ return [_object valuesForKeys:_keys];
+}
+
+/* capability */
+
+- (BOOL)handlesFetchSpecification:(EOFetchSpecification *)_fspec {
+ EOEntity *entity;
+
+ entity = [[self database] entityNamed:[_fspec entityName]];
+ return entity ? YES : NO;
+}
+
+/* graph */
+
+- (BOOL)ownsObject:(id)_object {
+ EOEntity *entity;
+
+ entity = [[self database] entityNamed:[_object entityName]];
+ return entity ? YES : NO;
+}
+
+- (BOOL)ownsGlobalID:(EOGlobalID *)_oid {
+ EOEntity *entity;
+
+ if (![_oid respondsToSelector:@selector(entityName)])
+ return NO;
+
+ entity = [[self database] entityNamed:[(id)_oid entityName]];
+ return entity ? YES : NO;
+}
+
+@end /* EODatabaseContext(NewInEOF2) */
--- /dev/null
+/*
+ EODatabaseFault.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ Author: Helge Hess <helge.hess@mdlink.de>
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "EODatabaseFault.h"
+#import "EODatabase.h"
+#import "EODatabaseChannel.h"
+#import "EOEntity.h"
+#import "EOFExceptions.h"
+#import "EODatabaseFaultResolver.h"
+#import "EOArrayProxy.h"
+#import "common.h"
+
+#if NeXT_RUNTIME || APPLE_RUNTIME
+# include <objc/objc-class.h>
+#endif
+
+typedef struct {
+ Class isa;
+} *my_objc_object;
+
+#define object_is_instance(object) \
+ ((object!=nil)&&CLS_ISCLASS(((my_objc_object)object)->isa))
+
+/*
+ * EODatabaseFault class
+ */
+
+@implementation EODatabaseFault
+
+// Fault class methods
+
++ (id)objectFaultWithPrimaryKey:(NSDictionary *)key
+ entity:(EOEntity *)entity
+ databaseChannel:(EODatabaseChannel *)channel
+ zone:(NSZone *)zone
+{
+ EODatabaseFault *fault = nil;
+
+ fault = [channel allocateObjectForRow:key entity:entity zone:zone];
+
+ if (fault == nil)
+ return nil;
+
+ if ([fault class]->instance_size < ((Class)self)->instance_size) {
+ [fault autorelease];
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"Instances from class %@ must be at least %d in size "
+ @"to fault",
+ NSStringFromClass([fault class]),
+ ((Class)self)->instance_size];
+ }
+ fault->faultResolver = [[EOObjectFault alloc] initWithPrimaryKey:key
+ entity:entity databaseChannel:channel zone:zone
+ targetClass:fault->isa];
+ fault->isa = self;
+
+ return (EODatabaseFault *)AUTORELEASE(fault);
+}
+
++ (NSArray*)arrayFaultWithQualifier:(EOSQLQualifier*)qualifier
+ fetchOrder:(NSArray*)fetchOrder
+ databaseChannel:(EODatabaseChannel*)channel
+ zone:(NSZone*)zone
+{
+ return [EOArrayProxy arrayProxyWithQualifier:qualifier
+ fetchOrder:fetchOrder
+ channel:channel];
+#if 0
+ EODatabaseFault* fault;
+
+ fault = [NSMutableArray allocWithZone:zone];
+
+ if ([fault class]->instance_size < ((Class)(self))->instance_size) {
+ (void)AUTORELEASE(fault);
+ THROW([[InvalidArgumentException alloc]
+ initWithFormat:
+ @"Instances from class %s must be at least %d "
+ @"in size to fault",
+ NSStringFromClass([fault class]),
+ ((Class)self)->instance_size]);
+ }
+ fault->faultResolver = [[EOArrayFault alloc] initWithQualifier:qualifier
+ fetchOrder:fetchOrder databaseChannel:channel zone:zone
+ targetClass:fault->isa fault:fault];
+ fault->isa = self;
+
+ return (NSArray*)AUTORELEASE(fault);
+#endif
+}
+
+// no more garbage collecting
++ (NSArray *)gcArrayFaultWithQualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ databaseChannel:(EODatabaseChannel *)channel
+ zone:(NSZone *)zone
+{
+ EODatabaseFault *fault;
+
+ fault = [NSMutableArray allocWithZone:zone];
+
+ if ([fault class]->instance_size < ((Class)(self))->instance_size) {
+ (void)[fault autorelease];
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"Instances from class %s must be at least %d "
+ @"in size to fault",
+ NSStringFromClass([fault class]),
+ ((Class)self)->instance_size];
+ }
+ fault->faultResolver = [[EOArrayFault alloc] initWithQualifier:qualifier
+ fetchOrder:fetchOrder databaseChannel:channel zone:zone
+ targetClass:fault->isa];
+ fault->isa = self;
+
+ return (NSArray *)AUTORELEASE(fault);
+}
+
++ (NSDictionary *)primaryKeyForFault:(id)fault {
+ EODatabaseFault *aFault = (EODatabaseFault *)fault;
+
+ // Check that argument is fault
+ if (aFault->isa != self)
+ return nil;
+
+ return [(EODatabaseFaultResolver *)aFault->faultResolver primaryKey];
+}
+
++ (EOEntity *)entityForFault:(id)fault {
+ EODatabaseFault *aFault = (EODatabaseFault *)fault;
+
+ // Check that argument is fault
+ if (aFault->isa != self)
+ return nil;
+
+ return [(EODatabaseFaultResolver *)aFault->faultResolver entity];
+}
+
++ (EOSQLQualifier *)qualifierForFault:(id)fault {
+ EODatabaseFault *aFault = (EODatabaseFault *)fault;
+
+ // Check that argument is fault
+ if (aFault->isa != self)
+ return nil;
+
+ return [(EODatabaseFaultResolver *)aFault->faultResolver qualifier];
+}
+
++ (NSArray *)fetchOrderForFault:(id)fault {
+ EODatabaseFault *aFault = (EODatabaseFault *)fault;
+
+ // Check that argument is fault
+ if (aFault->isa != self)
+ return nil;
+
+ return [(EODatabaseFaultResolver *)aFault->faultResolver fetchOrder];
+}
+
++ (EODatabaseChannel *)databaseChannelForFault:fault {
+ EODatabaseFault *aFault = (EODatabaseFault *)fault;
+
+ // Check that argument is fault
+ if (aFault->isa != self)
+ return nil;
+
+ return [(EODatabaseFaultResolver *)aFault->faultResolver databaseChannel];
+}
+
+- (void)dealloc {
+ [EODatabase forgetObject:self];
+ [super dealloc];
+}
+
+// Forwarding stuff
+
++ (void)initialize {
+ // Must be here as initialize is called for each root class
+ // without asking if it responds to it !
+}
+
+- (EOEntity *)entity {
+ return [EODatabaseFault entityForFault:self];
+}
+
+@end /* EODatabaseFault */
+
+/*
+ * Informal protocol that informs an instance that a to-one
+ * relationship could not be resoved to get data for self.
+ * Its implementation in NSObject raises NSObjectNotAvailableException.
+ */
+
+@implementation NSObject(EOUnableToFaultToOne)
+
+- (void)unableToFaultWithPrimaryKey:(NSDictionary*)key
+ entity:(EOEntity*)entity
+ databaseChannel:(EODatabaseChannel*)channel
+{
+ // TODO - throw exception form derived class
+ [[[ObjectNotAvailableException alloc]
+ initWithFormat:@"cannot fault to-one for primary key %@ entity %@",
+ [key description], [entity name]] raise];
+}
+
+@end /* NSObject(EOUnableToFaultToOne) */
+
+@implementation EOFault(EOUnableToFaultToOne)
+
+- (void)unableToFaultWithPrimaryKey:(NSDictionary*)key
+ entity:(EOEntity *)entity
+ databaseChannel:(EODatabaseChannel*)channel
+{
+ // TODO - throw exception from derived class
+ [[[ObjectNotAvailableException alloc]
+ initWithFormat:@"cannot fault to-one for primary key %@ entity %@",
+ [key description], [entity name]]
+ raise];
+}
+
+@end /* EOFault(EOUnableToFaultToOne) */
--- /dev/null
+/*
+ EODatabaseFaultResolver.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ Author: Helge Hess <helge.hess@mdlink.de>
+ Date: 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EODatabaseFaultResolver.h"
+#import "EODatabaseChannel.h"
+#import "EODatabaseContext.h"
+#import "EOEntity.h"
+#import "EODatabaseFault.h"
+#import "EOSQLQualifier.h"
+#import "EOGenericRecord.h"
+
+@implementation EODatabaseFaultResolver
+
+- (id)initWithDatabaseChannel:(EODatabaseChannel *)aChannel
+ zone:(NSZone *)aZone
+ targetClass:(Class)_targetClass
+{
+ if ((self = [super init])) {
+ self->channel = aChannel;
+ self->targetClass = _targetClass;
+ self->zone = aZone;
+ self->faultReferences = 0;
+ }
+ return self;
+}
+
+- (BOOL)fault {
+ return NO;
+}
+
+- (EODatabaseChannel *)databaseChannel {
+ return self->channel;
+}
+
+- (Class)targetClass; {
+ return self->targetClass;
+}
+
+- (NSDictionary *)primaryKey {
+ return nil;
+}
+- (EOEntity *)entity {
+ return nil;
+}
+- (EOSQLQualifier *)qualifier {
+ return nil;
+}
+- (NSArray *)fetchOrder {
+ return nil;
+}
+
+@end /* EODatabaseFaultResolver */
+
+@implementation EOArrayFault
+
+- (id)initWithQualifier:(EOSQLQualifier *)aQualifier
+ fetchOrder:(NSArray *)aFetchOrder
+ databaseChannel:(EODatabaseChannel *)aChannel
+ zone:(NSZone *)aZone
+ targetClass:(Class)_targetClass
+{
+
+ if ((self = [super initWithDatabaseChannel:aChannel zone:aZone
+ targetClass:_targetClass])) {
+ self->qualifier = RETAIN(aQualifier);
+ self->fetchOrder = RETAIN(aFetchOrder);
+
+ NSAssert([self->targetClass isKindOfClass:[NSArray class]],
+ @"target class of an array fault is not an array class");
+ }
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->qualifier);
+ RELEASE(self->fetchOrder);
+ [super dealloc];
+}
+
+- (EOEntity *)entity {
+ return [self->qualifier entity];
+}
+
+- (EOSQLQualifier *)qualifier {
+ return self->qualifier;
+}
+
+- (NSArray *)fetchOrder {
+ return self->fetchOrder;
+}
+
+- (void)completeInitializationOfObject:(id)_fault {
+ unsigned int oldRetainCount;
+ BOOL inTransaction;
+
+ NSAssert([self->targetClass isKindOfClass:[NSArray class]],
+ @"target class of an array fault is not an array class");
+
+ oldRetainCount = [_fault retainCount];
+
+ [EOFault clearFault:_fault];
+ NSAssert([(id)_fault init] == _fault, @"init modified fault reference ..");
+
+ NSAssert([_fault isKindOfClass:[NSArray class]],
+ @"resolved-object of an array fault is not of an array class");
+
+ if ([self->channel isFetchInProgress]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"attempt to fault with busy channel: %@", self];
+ }
+
+ inTransaction = [[self->channel databaseContext] transactionNestingLevel] > 0;
+ if (!inTransaction) {
+ if (![[self->channel databaseContext] beginTransaction]) {
+ [NSException raise:@"DBFaultResolutionException"
+ format:@"could not begin transaction to resolve fault !"];
+ }
+ }
+
+ if (![self->channel selectObjectsDescribedByQualifier:self->qualifier
+ fetchOrder:self->fetchOrder]) {
+ if (!inTransaction)
+ [[self->channel databaseContext] rollbackTransaction];
+ [NSException raise:@"DBFaultResolutionException"
+ format:@"select for fault failed !"];
+ }
+
+ { // fetch objects
+ id object;
+
+ while ((object = [self->channel fetchWithZone:zone])) {
+ if (![object isKindOfClass:[EOGenericRecord class]]) {
+ NSLog(@"Object is of class %@", NSStringFromClass([object class]));
+ abort();
+ }
+ NSAssert([object isKindOfClass:[EOGenericRecord class]],
+ @"fetched object is not a EOGenericRecord ..");
+ [(id)_fault addObject:object];
+ }
+
+ object = nil;
+ }
+
+ [self->channel cancelFetch];
+
+ if (!inTransaction) {
+ if (![[self->channel databaseContext] commitTransaction]) {
+ NSLog(@"WARNING: could not commit fault's transaction !");
+ [NSException raise:@"DBFaultResolutionException"
+ format:@"could not commit fault's transaction !"];
+ }
+ }
+
+#if MOF2_DEBUG
+ if ([fault retainCount] != oldRetainCount) {
+ NSLog(@"fault retain count does not match replacement (old=%d, new=%d)",
+ oldRetainCount, [fault retainCount]);
+ }
+#endif
+
+ NSAssert([_fault retainCount] == oldRetainCount,
+ @"fault retain count does not match replacement's retain count");
+}
+
+- (NSString *)descriptionForObject:(id)_fault {
+ return [NSString stringWithFormat:
+ @"<Array fault 0x%x (qualifier=%@, order=%@, channel=%@)>",
+ _fault, qualifier, fetchOrder, channel];
+}
+
+@end /* EOArrayFault */
+
+@implementation EOObjectFault
+
+- (id)initWithPrimaryKey:(NSDictionary *)_key
+ entity:(EOEntity *)anEntity
+ databaseChannel:(EODatabaseChannel *)aChannel
+ zone:(NSZone *)aZone
+ targetClass:(Class)_targetClass
+{
+ [super initWithDatabaseChannel:aChannel
+ zone:aZone
+ targetClass:_targetClass];
+ self->entity = RETAIN(anEntity);
+ self->primaryKey = RETAIN(_key);
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->entity);
+ RELEASE(self->primaryKey);
+ [super dealloc];
+}
+
+- (NSDictionary*)primaryKey {
+ return self->primaryKey;
+}
+
+- (EOEntity *)entity {
+ return self->entity;
+}
+
+- (void)completeInitializationOfObject:(id)_fault {
+ EOSQLQualifier *qualifier = nil;
+ BOOL channelIsOpen = YES;
+ BOOL inTransaction = YES;
+ id object = nil;
+
+ if ([self->channel isFetchInProgress]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"attempt to fault with busy channel: %@", self];
+ }
+
+ qualifier =
+ [EOSQLQualifier qualifierForPrimaryKey:primaryKey entity:self->entity];
+ if (qualifier == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"could not build qualifier for fault: %@", self];
+ }
+
+ channelIsOpen = [self->channel isOpen];
+ if (!channelIsOpen) {
+ if (![self->channel openChannel])
+ goto done;
+ }
+
+ inTransaction = [[self->channel databaseContext] transactionNestingLevel] != 0;
+ if (!inTransaction) {
+ if (![[self->channel databaseContext] beginTransaction]) {
+ if (!channelIsOpen) [self->channel closeChannel];
+ goto done;
+ }
+ }
+
+ if (![self->channel selectObjectsDescribedByQualifier:qualifier fetchOrder:nil]) {
+ if (!inTransaction) {
+ [[self->channel databaseContext] rollbackTransaction];
+ if (!channelIsOpen) [self->channel closeChannel];
+ }
+ goto done;
+ }
+
+ // Fetch the object
+ object = [self->channel fetchWithZone:zone];
+
+ // The fetch failed!
+ if (object == nil) {
+ [self->channel cancelFetch];
+ if (!inTransaction) [[self->channel databaseContext] rollbackTransaction];
+ if (!channelIsOpen) [self->channel closeChannel];
+ goto done;
+ }
+
+ // Make sure we only fetched one object
+ if ([self->channel fetchWithZone:zone])
+ object = nil;
+
+ [self->channel cancelFetch];
+
+ if (!inTransaction) {
+ if (![[self->channel databaseContext] commitTransaction]) object = nil;
+ if (!channelIsOpen) [self->channel closeChannel];
+ }
+
+ done:
+ if (object != _fault) {
+ if ([EOFault isFault:_fault])
+ [EOFault clearFault:_fault];
+
+ [(id)_fault unableToFaultWithPrimaryKey:primaryKey
+ entity:self->entity
+ databaseChannel:self->channel];
+ }
+}
+
+- (NSString *)descriptionForObject:(id)_fault {
+ return [NSString stringWithFormat:
+ @"<Object fault 0x%X "
+ @"(class=%@, entity=%@, key=%@, channel=%@)>",
+ _fault,
+ NSStringFromClass(targetClass),
+ [entity name],
+ [primaryKey description],
+ [channel description]];
+}
+
+@end /* EOObjectFault */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOEntity+Factory.m 1 2004-08-20 10:38:46Z znek $
+
+#include <GDLAccess/EOEntity+Factory.h>
+#include <GDLAccess/EOAttribute.h>
+#include <EOControl/EONull.h>
+#include <EOControl/EOKeyValueCoding.h>
+#include "common.h"
+
+@interface NSObject(PKeyInitializer)
+- (id)initWithPrimaryKey:(NSDictionary *)_pkey entity:(EOEntity *)_entity;
+@end
+
+@implementation EOEntity(AttributeNames)
+
+- (NSArray *)attributeNames {
+ NSMutableArray *attrNames = [[[NSMutableArray alloc] init] autorelease];
+ NSEnumerator *attrs = [self->attributes objectEnumerator];
+ EOAttribute *attr = nil;
+
+ while ((attr = [attrs nextObject]))
+ [attrNames addObject:[attr name]];
+
+ return attrNames;
+}
+
+@end /* EOEntity(AttributeNames) */
+
+@implementation EOEntity(PrimaryKeys)
+
+- (BOOL)isPrimaryKeyAttribute:(EOAttribute *)_attribute {
+ NSEnumerator *pkeys = [self->primaryKeyAttributeNames objectEnumerator];
+ NSString *aname = [_attribute name];
+ NSString *n = nil;
+
+ while ((n = [pkeys nextObject])) {
+ if ([aname isEqualToString:n])
+ return YES;
+ }
+ return NO;
+}
+
+- (unsigned)primaryKeyCount {
+ return [self->primaryKeyAttributeNames count];
+}
+
+@end /* EOEntity(PrimaryKeys) */
+
+@implementation EOEntity(ObjectFactory)
+
+- (id)produceNewObjectWithPrimaryKey:(NSDictionary *)_key {
+ /* Note: used by LSDBObjectNewCommand */
+ Class objectClass = Nil;
+ id obj;
+
+ objectClass = NSClassFromString([self className]);
+ NSAssert(objectClass != nil, @"no enterprise object class set in entity");
+
+ obj = [objectClass alloc];
+ NSAssert(objectClass != nil, @"could not allocate enterprise object");
+
+ if ([obj respondsToSelector:@selector(initWithPrimaryKey:entity:)])
+ [obj initWithPrimaryKey:_key entity:self];
+ else
+ [obj init];
+
+ return AUTORELEASE(obj);
+}
+
+- (void)setAttributesOfObjectToEONull:(id)_object {
+ static EONull *null = nil;
+ NSEnumerator *attrs;
+ EOAttribute *attr;
+ int pkeyCount;
+
+ if (null == nil)
+ null = [[NSNull null] retain];
+
+ attrs = [self->attributes objectEnumerator];
+ attr = nil;
+ pkeyCount = [self->primaryKeyAttributeNames count];
+
+ NSAssert(NSClassFromString([self className]) == [_object class],
+ @"object does not belong to entity");
+
+ while ((attr = [attrs nextObject])) {
+ if (pkeyCount > 0) {
+ if ([self isPrimaryKeyAttribute:attr]) {
+ pkeyCount--;
+ continue;
+ }
+ }
+
+ [_object takeValue:null forKey:[attr name]];
+ }
+}
+
+@end /* EOEntity(ObjectFactory) */
--- /dev/null
+/*
+ EOEntity.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ Author: Helge Hess <helge.hess@mdlink.de>
+ Date: November 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOEntity.h"
+#import "EOAttribute.h"
+#import "EOFExceptions.h"
+#import "EOModel.h"
+#import "EOPrimaryKeyDictionary.h"
+#import "EOSQLQualifier.h"
+#import "EORelationship.h"
+#import <EOControl/EOKeyValueCoding.h>
+#import <EOControl/EOKeyGlobalID.h>
+
+static int _compareByName(id obj1, id obj2, void * context);
+
+@interface NSObject(MappedArrayProtocol)
+- (NSArray *)mappedArrayUsingSelector:(SEL)_selector;
+@end
+
+@interface NSString(EntityBeautify)
+- (NSString *)_beautifyEntityName;
+@end
+
+@implementation EOEntity
+
+- (id)init {
+ if ((self = [super init])) {
+ self->attributes = [[NSArray alloc] init];
+ self->attributesByName = [[NSMutableDictionary alloc] init];
+ self->relationships = [[NSArray alloc] init];
+ self->relationshipsByName = [[NSMutableDictionary alloc] init];
+ self->classProperties = [[NSArray alloc] init];
+ self->model = nil;
+ }
+ return self;
+}
+
+- (void)resetAttributes {
+ [self->attributes makeObjectsPerformSelector:@selector(resetEntity)];
+}
+- (void)resetRelationships {
+ [self->relationships makeObjectsPerformSelector:@selector(resetEntities)];
+}
+
+- (void)dealloc {
+ self->model = nil;
+ RELEASE(self->qualifier);
+ [self resetAttributes];
+ RELEASE(self->attributes);
+ RELEASE(self->attributesByName);
+ [self resetRelationships];
+ RELEASE(self->relationships);
+ RELEASE(self->relationshipsByName);
+ RELEASE(self->primaryKeyAttributes);
+ RELEASE(self->classProperties);
+ RELEASE(self->attributesUsedForLocking);
+ RELEASE(self->attributesUsedForInsert);
+ RELEASE(self->attributesUsedForFetch);
+ RELEASE(self->relationsUsedForFetch);
+ RELEASE(self->name); self->name = nil;
+ RELEASE(self->className); self->className = nil;
+ RELEASE(self->externalName); self->externalName = nil;
+ RELEASE(self->externalQuery); self->externalQuery = nil;
+ RELEASE(self->userDictionary); self->userDictionary = nil;
+ RELEASE(self->primaryKeyAttributeNames);
+ self->primaryKeyAttributeNames = nil;
+ RELEASE(self->attributesNamesUsedForInsert);
+ self->attributesNamesUsedForInsert = nil;
+ RELEASE(self->classPropertyNames); self->classPropertyNames = nil;
+ [super dealloc];
+}
+
+// These methods should be here to let the library work with NeXT foundation
+- (id)copy {
+ return RETAIN(self);
+}
+- (id)copyWithZone:(NSZone *)_zone {
+ return RETAIN(self);
+}
+
+// Is equal only if same name; used to make aliasing ordering stable
+- (unsigned)hash {
+ return [name hash];
+}
+
+- (id)initWithName:(NSString *)_name {
+ [self init];
+ ASSIGN(name, _name);
+ return self;
+}
+
+- (BOOL)setName:(NSString *)_name {
+ if([model entityNamed:name]) return NO;
+ ASSIGN(name, _name);
+ return YES;
+}
+
++ (BOOL)isValidName:(NSString *)attributeName {
+ unsigned len = [attributeName cStringLength];
+ char buf[len + 1];
+ const char *s;
+
+ s = buf;
+ [attributeName getCString:buf];
+
+ if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#')
+ return NO;
+
+ for(++s; *s; s++)
+ if(!isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#' && *s != '$')
+ return NO;
+
+ return YES;
+}
+
+- (BOOL)addAttribute:(EOAttribute *)attribute {
+ NSString* attributeName = [attribute name];
+
+ if([self->attributesByName objectForKey:attributeName])
+ return NO;
+
+ if([self->relationshipsByName objectForKey:attributeName])
+ return NO;
+
+ if([self createsMutableObjects])
+ [(NSMutableArray*)self->attributes addObject:attribute];
+ else {
+ id newAttributes = [self->attributes arrayByAddingObject:attribute];
+ ASSIGN(self->attributes, newAttributes);
+ }
+
+ [self->attributesByName setObject:attribute forKey:attributeName];
+ [attribute setEntity:self];
+ [self invalidatePropertiesCache];
+ return YES;
+}
+
+- (void)removeAttributeNamed:(NSString *)attributeName {
+ id attribute = [self->attributesByName objectForKey:attributeName];
+
+ if(attribute) {
+ [attribute resetEntity];
+ if([self createsMutableObjects])
+ [(NSMutableArray*)attributes removeObject:attribute];
+ else {
+ self->attributes = [AUTORELEASE(self->attributes) mutableCopy];
+ [(NSMutableArray*)self->attributes removeObject:attribute];
+ self->attributes = [AUTORELEASE(self->attributes) copy];
+ }
+ [self->attributesByName removeObjectForKey:attributeName];
+ [self invalidatePropertiesCache];
+ }
+}
+
+- (EOAttribute *)attributeNamed:(NSString *)attributeName {
+ return [self->attributesByName objectForKey:attributeName];
+}
+
+- (BOOL)addRelationship:(EORelationship *)relationship {
+ NSString* relationshipName = [relationship name];
+
+ if([self->attributesByName objectForKey:relationshipName])
+ return NO;
+
+ if([self->relationshipsByName objectForKey:relationshipName])
+ return NO;
+
+ if([self createsMutableObjects])
+ [(NSMutableArray*)relationships addObject:relationship];
+ else {
+ id newRelationships = [self->relationships arrayByAddingObject:relationship];
+ ASSIGN(self->relationships, newRelationships);
+ }
+
+ [self->relationshipsByName setObject:relationship forKey:relationshipName];
+ [relationship setEntity:self];
+ [self invalidatePropertiesCache];
+ return YES;
+}
+
+- (void)removeRelationshipNamed:(NSString*)relationshipName {
+ id relationship = [relationshipsByName objectForKey:relationshipName];
+
+ if(relationship) {
+ [relationship setEntity:nil];
+ if([self createsMutableObjects])
+ [(NSMutableArray*)self->relationships removeObject:relationship];
+ else {
+ self->relationships = [AUTORELEASE(self->relationships) mutableCopy];
+ [(NSMutableArray*)self->relationships removeObject:relationship];
+ self->relationships = [AUTORELEASE(relationships) copy];
+ }
+ [self->relationshipsByName removeObjectForKey:relationship];
+ [self invalidatePropertiesCache];
+ }
+}
+
+- (EORelationship*)relationshipNamed:(NSString *)relationshipName {
+ if([relationshipName isNameOfARelationshipPath]) {
+ NSArray *defArray;
+ int i, count;
+ EOEntity *currentEntity = self;
+ NSString *relName = nil;
+ EORelationship *relationship = nil;
+
+ defArray = [relationshipName componentsSeparatedByString:@"."];
+ relName = [defArray objectAtIndex:0];
+
+ for(i = 0, count = [defArray count]; i < count; i++) {
+ if(![EOEntity isValidName:relName])
+ return nil;
+ relationship = [currentEntity->relationshipsByName objectForKey:relName];
+ if(relationship == nil)
+ return nil;
+ currentEntity = [relationship destinationEntity];
+ }
+ return relationship;
+ }
+ else
+ return [self->relationshipsByName objectForKey:relationshipName];
+}
+
+- (BOOL)setPrimaryKeyAttributes:(NSArray *)keys {
+ int i, count = [keys count];
+
+ for(i = 0; i < count; i++)
+ if(![self isValidPrimaryKeyAttribute:[keys objectAtIndex:i]])
+ return NO;
+
+ RELEASE(self->primaryKeyAttributes);
+ RELEASE(self->primaryKeyAttributeNames);
+
+ if([keys isKindOfClass:[NSArray class]]
+ || [keys isKindOfClass:[NSMutableArray class]])
+ self->primaryKeyAttributes = [keys copy];
+ else
+ self->primaryKeyAttributes = [[NSArray alloc] initWithArray:keys];
+
+ self->primaryKeyAttributeNames = [NSMutableArray arrayWithCapacity:count];
+ for(i = 0; i < count; i++) {
+ id key = [keys objectAtIndex:i];
+
+ [(NSMutableArray*)self->primaryKeyAttributeNames
+ addObject:[(EOAttribute*)key name]];
+ }
+ self->primaryKeyAttributeNames
+ = RETAIN([self->primaryKeyAttributeNames
+ sortedArrayUsingSelector:@selector(compare:)]);
+
+ [self invalidatePropertiesCache];
+
+ return YES;
+}
+
+- (BOOL)isValidPrimaryKeyAttribute:(EOAttribute*)anAttribute {
+ if(![anAttribute isKindOfClass:[EOAttribute class]])
+ return NO;
+
+ if([self->attributesByName objectForKey:[anAttribute name]])
+ return YES;
+
+ return NO;
+}
+
+- (NSDictionary *)primaryKeyForRow:(NSDictionary *)_row {
+ return [EOPrimaryKeyDictionary dictionaryWithKeys:
+ self->primaryKeyAttributeNames
+ fromDictionary:_row];
+}
+
+- (NSDictionary *)snapshotForRow:(NSDictionary *)aRow {
+ NSArray *array;
+ int i, n;
+ NSMutableDictionary *dict;
+
+ array = [self attributesUsedForLocking];
+ n = [array count];
+ dict = [NSMutableDictionary dictionaryWithCapacity:n];
+
+ for (i = 0; i < n; i++) {
+ EOAttribute *attribute;
+ NSString *columnName;
+ NSString *attributeName;
+ id value;
+
+ attribute = [array objectAtIndex:i];
+ columnName = [attribute columnName];
+ attributeName = [attribute name];
+
+ value = [aRow objectForKey:attributeName];
+
+#if DEBUG
+ NSAssert1(columnName, @"missing column name in attribute %@ !", attribute);
+ NSAssert3(value, @"missing value for column '%@' (attr '%@') in row %@",
+ columnName, attribute, aRow);
+#endif
+
+ [dict setObject:value forKey:attributeName];
+ }
+ return dict;
+}
+
+/* Getting attributes used for database oprations */
+
+- (NSArray*)attributesUsedForInsert
+{
+ if (!flags.isPropertiesCacheValid)
+ [self validatePropertiesCache];
+ return self->attributesUsedForInsert;
+}
+
+- (NSArray *)attributesUsedForFetch {
+ if (!flags.isPropertiesCacheValid)
+ [self validatePropertiesCache];
+ return self->attributesUsedForFetch;
+}
+
+- (NSArray *)relationsUsedForFetch {
+ if (!flags.isPropertiesCacheValid)
+ [self validatePropertiesCache];
+ return self->relationsUsedForFetch;
+}
+
+- (NSArray *)attributesNamesUsedForInsert {
+ if (!flags.isPropertiesCacheValid)
+ [self validatePropertiesCache];
+ return self->attributesNamesUsedForInsert;
+}
+
+- (BOOL)setClassProperties:(NSArray *)properties {
+ int i, count = [properties count];
+
+ for(i = 0; i < count; i++)
+ if(![self isValidClassProperty:[properties objectAtIndex:i]])
+ return NO;
+
+ RELEASE(self->classProperties); self->classProperties = nil;
+ RELEASE(self->classPropertyNames); self->classPropertyNames = nil;
+
+ if([properties isKindOfClass:[NSArray class]]
+ || [properties isKindOfClass:[NSMutableArray class]]) {
+ self->classProperties = [properties copyWithZone:[self zone]];
+ }
+ else {
+ self->classProperties = [[NSArray allocWithZone:[self zone]]
+ initWithArray:properties];
+ }
+
+ self->classPropertyNames = [NSMutableArray arrayWithCapacity:count];
+ for(i = 0; i < count; i++) {
+ id property = [properties objectAtIndex:i];
+ [(NSMutableArray*)classPropertyNames addObject:[(EOAttribute*)property name]];
+ }
+ self->classPropertyNames = [self->classPropertyNames copyWithZone:[self zone]];
+ [self invalidatePropertiesCache];
+
+ return YES;
+}
+
+- (BOOL)isValidClassProperty:(id)aProperty {
+ id thePropertyName = nil;
+
+ if(!([aProperty isKindOfClass:[EOAttribute class]]
+ || [aProperty isKindOfClass:[EORelationship class]]))
+ return NO;
+
+ thePropertyName = [(EOAttribute*)aProperty name];
+ if([self->attributesByName objectForKey:thePropertyName]
+ || [self->relationshipsByName objectForKey:thePropertyName])
+ return YES;
+
+ return NO;
+}
+
+- (NSArray *)relationshipsNamed:(NSString *)_relationshipPath {
+ if([_relationshipPath isNameOfARelationshipPath]) {
+ NSMutableArray *myRelationships = [[NSMutableArray alloc] init];
+ NSArray *defArray = [_relationshipPath componentsSeparatedByString:@"."];
+ int i, count = [defArray count] - 1;
+ EOEntity *currentEntity = self;
+ NSString *relName = nil;
+ id relation = nil;
+
+ for(i = 0; i < count; i++) {
+ relName = [defArray objectAtIndex:i];
+
+ if([EOEntity isValidName:relName]) {
+ relation = [currentEntity relationshipNamed:relName];
+ if(relation) {
+ [myRelationships addObject:relation];
+ currentEntity = [relation destinationEntity];
+ }
+ }
+ }
+ return AUTORELEASE(myRelationships);
+ }
+ return nil;
+}
+
+- (id)propertyNamed:(NSString *)_name {
+ if([_name isNameOfARelationshipPath]) {
+ NSArray *defArray = [_name componentsSeparatedByString:@"."];
+ EOEntity *currentEntity = self;
+ NSString *propertyName;
+ int i = 0, count = [defArray count];
+ id property;
+
+ for(; i < count - 1; i++) {
+ propertyName = [defArray objectAtIndex:i];
+ if(![EOEntity isValidName:propertyName])
+ return nil;
+ property = [currentEntity propertyNamed:propertyName];
+ if(!property)
+ return nil;
+
+ currentEntity = [property destinationEntity];
+ }
+ propertyName = [defArray lastObject];
+ property = [currentEntity attributeNamed:propertyName];
+ return property;
+ }
+ else {
+ id attribute = nil;
+ id relationship = nil;
+
+ attribute = [self->attributesByName objectForKey:_name];
+ if(attribute)
+ return attribute;
+
+ relationship = [self->relationshipsByName objectForKey:_name];
+ if(relationship)
+ return relationship;
+ }
+
+ return nil;
+}
+
+- (BOOL)setAttributesUsedForLocking:(NSArray *)_attributes {
+ int i, count = [_attributes count];
+
+ for(i = 0; i < count; i++)
+ if(![self isValidAttributeUsedForLocking:
+ [_attributes objectAtIndex:i]])
+ return NO;
+
+ RELEASE(self->attributesUsedForLocking);
+
+ if([_attributes isKindOfClass:[NSArray class]]
+ || [_attributes isKindOfClass:[NSMutableArray class]])
+ self->attributesUsedForLocking = [_attributes copy];
+ else
+ self->attributesUsedForLocking = [[NSArray alloc] initWithArray:_attributes];
+ [self invalidatePropertiesCache];
+
+ return YES;
+}
+
+- (BOOL)isValidAttributeUsedForLocking:(EOAttribute*)anAttribute {
+ if(!([anAttribute isKindOfClass:[EOAttribute class]]
+ && [self->attributesByName objectForKey:[anAttribute name]]))
+ return NO;
+
+ if([anAttribute isDerived])
+ return NO;
+
+ return YES;
+}
+
+- (void)setModel:(EOModel *)aModel {
+ self->model = aModel; /* non-retained */
+}
+- (void)resetModel {
+ self->model = nil;
+}
+- (BOOL)hasModel {
+ return (self->model != nil) ? YES : NO;
+}
+
+- (void)setClassName:(NSString *)_name {
+ if(!_name) _name = @"EOGenericRecord";
+ ASSIGN(self->className, _name);
+}
+
+- (void)setReadOnly:(BOOL)flag
+{
+ flags.isReadOnly = flag;
+}
+
+- (BOOL)referencesProperty:(id)property {
+ id propertyName = [(EOAttribute*)property name];
+
+ if([self->attributesByName objectForKey:propertyName]
+ || [self->relationshipsByName objectForKey:propertyName])
+ return YES;
+ return NO;
+}
+
+- (EOSQLQualifier*)qualifier {
+ if (self->qualifier == nil) {
+ self->qualifier = [[EOSQLQualifier allocWithZone:[self zone]]
+ initWithEntity:self
+ qualifierFormat:nil];
+ }
+ return self->qualifier;
+}
+
+// accessors
+
+- (void)setExternalName:(NSString*)_name {
+ ASSIGN(externalName, _name);
+}
+- (NSString *)externalName {
+ return self->externalName;
+}
+
+- (void)setExternalQuery:(NSString*)query {
+ ASSIGN(externalQuery, query);
+}
+- (NSString *)externalQuery {
+ return self->externalQuery;
+}
+
+- (void)setUserDictionary:(NSDictionary*)dict {
+ ASSIGN(userDictionary, dict);
+}
+- (NSDictionary *)userDictionary {
+ return self->userDictionary;
+}
+
+- (NSString *)name {
+ return self->name;
+}
+- (BOOL)isReadOnly {
+ return self->flags.isReadOnly;
+}
+- (NSString *)className {
+ return self->className;
+}
+- (NSArray *)attributesUsedForLocking {
+ return self->attributesUsedForLocking;
+}
+- (NSArray *)classPropertyNames {
+ return self->classPropertyNames;
+}
+- (NSArray *)classProperties {
+ return self->classProperties;
+}
+- (NSArray *)primaryKeyAttributes {
+ return self->primaryKeyAttributes;
+}
+- (NSArray *)primaryKeyAttributeNames {
+ return self->primaryKeyAttributeNames;
+}
+- (NSArray *)relationships {
+ return self->relationships;
+}
+- (EOModel *)model {
+ return self->model;
+}
+- (NSArray *)attributes {
+ return self->attributes;
+}
+
+@end /* EOEntity */
+
+
+@implementation EOEntity (EOEntityCreation)
+
++ (EOEntity *)entityFromPropertyList:(id)propertyList model:(EOModel *)_model {
+ EOEntity *entity;
+ NSArray *array;
+ NSEnumerator *enumerator;
+ id attributePList;
+ id relationshipPList;
+
+ entity = AUTORELEASE([[EOEntity alloc] init]);
+ [entity setCreateMutableObjects:YES];
+
+ entity->name = RETAIN([propertyList objectForKey:@"name"]);
+ entity->className = RETAIN([propertyList objectForKey:@"className"]);
+ entity->externalName = RETAIN([propertyList objectForKey:@"externalName"]);
+ entity->externalQuery = RETAIN([propertyList objectForKey:@"externalQuery"]);
+ entity->userDictionary = RETAIN([propertyList objectForKey:@"userDictionary"]);
+
+ array = [propertyList objectForKey:@"attributes"];
+ enumerator = [array objectEnumerator];
+
+ while ((attributePList = [enumerator nextObject])) {
+ EOAttribute *attribute;
+
+ attribute = [EOAttribute attributeFromPropertyList:attributePList];
+
+ if (![entity addAttribute:attribute]) {
+ NSLog(@"duplicate name for attribute '%@' in entity '%@'",
+ [attribute name], [entity name]);
+ [_model errorInReading];
+ }
+ }
+
+ entity->attributesUsedForLocking
+ = RETAIN([propertyList objectForKey:@"attributesUsedForLocking"]);
+ entity->classPropertyNames
+ = RETAIN([propertyList objectForKey:@"classProperties"]);
+
+ if ((attributePList = [propertyList objectForKey:@"primaryKeyAttributes"])) {
+ entity->primaryKeyAttributeNames
+ = RETAIN([attributePList sortedArrayUsingSelector:@selector(compare:)]);
+ }
+
+ else
+ if ((attributePList = [propertyList objectForKey:@"primaryKeyAttribute"]))
+ entity->primaryKeyAttributeNames
+ = RETAIN([NSArray arrayWithObject:attributePList]);
+
+ array = [propertyList objectForKey:@"relationships"];
+ enumerator = [array objectEnumerator];
+ while((relationshipPList = [enumerator nextObject])) {
+ EORelationship *relationship
+ = [EORelationship relationshipFromPropertyList:relationshipPList
+ model:_model];
+
+ if(![entity addRelationship:relationship]) {
+ NSLog(@"duplicate name for relationship '%@' in entity '%@'",
+ [relationship name], [entity name]);
+ [_model errorInReading];
+ }
+ }
+
+ [entity setCreateMutableObjects:NO];
+
+ return entity;
+}
+
+- (void)replaceStringsWithObjects {
+ NSEnumerator *enumerator = nil;
+ EOAttribute *attribute = nil;
+ NSString *attributeName = nil;
+ NSString *propertyName = nil;
+ NSMutableArray *array = nil;
+ int i, count;
+
+ enumerator = [self->primaryKeyAttributeNames objectEnumerator];
+ RELEASE(self->primaryKeyAttributes);
+ self->primaryKeyAttributes = AUTORELEASE([NSMutableArray new]);
+
+ while ((attributeName = [enumerator nextObject])) {
+ attribute = [self attributeNamed:attributeName];
+
+ if((attribute == nil) || ![self isValidPrimaryKeyAttribute:attribute]) {
+ NSLog(@"invalid attribute name specified as primary key attribute "
+ @"'%s' in entity '%s'",
+ [attributeName cString], [name cString]);
+ [self->model errorInReading];
+ }
+ else
+ [(NSMutableArray*)self->primaryKeyAttributes addObject:attribute];
+ }
+ self->primaryKeyAttributes = [self->primaryKeyAttributes copy];
+
+ enumerator = [self->classPropertyNames objectEnumerator];
+ RELEASE(self->classProperties);
+ self->classProperties = AUTORELEASE([NSMutableArray new]);
+ while((propertyName = [enumerator nextObject])) {
+ id property;
+
+ property = [self propertyNamed:propertyName];
+ if(!property || ![self isValidClassProperty:property]) {
+ NSLog(@"invalid property '%s' specified as class property in "
+ @"entity '%s'",
+ [propertyName cString], [name cString]);
+ [self->model errorInReading];
+ }
+ else
+ [(NSMutableArray*)self->classProperties addObject:property];
+ }
+ self->classProperties = [self->classProperties copy];
+
+ array = AUTORELEASE([NSMutableArray new]);
+ [array setArray:self->attributesUsedForLocking];
+ RELEASE(self->attributesUsedForLocking);
+ count = [array count];
+ for(i = 0; i < count; i++) {
+ attributeName = [array objectAtIndex:i];
+ attribute = [self attributeNamed:attributeName];
+ if(!attribute || ![self isValidAttributeUsedForLocking:attribute]) {
+ NSLog(@"invalid attribute specified as attribute used for "
+ @"locking '%@' in entity '%@'", attributeName, name);
+ [self->model errorInReading];
+ }
+ else
+ [array replaceObjectAtIndex:i withObject:attribute];
+ }
+ self->attributesUsedForLocking = [array copy];
+}
+
+- (id)propertyList
+{
+ id propertyList;
+
+ propertyList = [NSMutableDictionary dictionary];
+ [self encodeIntoPropertyList:propertyList];
+ return propertyList;
+}
+
+- (void)setCreateMutableObjects:(BOOL)flag {
+ if(self->flags.createsMutableObjects == flag)
+ return;
+
+ self->flags.createsMutableObjects = flag;
+
+ if(self->flags.createsMutableObjects) {
+ self->attributes = [AUTORELEASE(self->attributes) mutableCopy];
+ self->relationships = [AUTORELEASE(self->relationships) mutableCopy];
+ }
+ else {
+ self->attributes = [AUTORELEASE(self->attributes) copy];
+ self->relationships = [AUTORELEASE(self->relationships) copy];
+ }
+}
+
+- (BOOL)createsMutableObjects {
+ return self->flags.createsMutableObjects;
+}
+
+#if 0
+static inline void _printIds(NSArray *a, const char *pfx, const char *indent) {
+ int i;
+ if (pfx == NULL) pfx = "";
+ if (indent == NULL) indent = " ";
+ printf("%s", pfx);
+ for (i = 0; i < [a count]; i++)
+ printf("%s0x%08X\n", indent, (unsigned)[a objectAtIndex:i]);
+}
+#endif
+
+static inline BOOL _containsObject(NSArray *a, id obj) {
+ id (*objAtIdx)(NSArray*, SEL, int idx);
+ register int i;
+
+ objAtIdx = (void *)[a methodForSelector:@selector(objectAtIndex:)];
+ for (i = [a count] - 1; i >= 0; i--) {
+ register id o;
+
+ o = objAtIdx(a, @selector(objectAtIndex:), i);
+ if (o == obj) return YES;
+ }
+ return NO;
+}
+
+- (void)validatePropertiesCache
+{
+ NSMutableArray *updAttr = [NSMutableArray new];
+ NSMutableArray *updName = [NSMutableArray new];
+ NSMutableArray *fetAttr = [NSMutableArray new];
+ NSMutableArray *fetRels = [NSMutableArray new];
+
+ int i;
+
+ [self invalidatePropertiesCache];
+
+#ifdef DEBUG
+ NSAssert((updAttr != nil) && (updName != nil) &&
+ (fetAttr != nil) && (fetRels != nil),
+ @"allocation of array failed !");
+
+ NSAssert(self->primaryKeyAttributes, @"no pkey attributes are set !");
+ NSAssert(self->attributesUsedForLocking, @"no locking attrs are set !");
+ NSAssert(self->classProperties, @"no class properties are set !");
+#endif
+
+ //_printIds(self->attributes, "attrs:\n", " ");
+ //_printIds(self->attributesUsedForLocking, "lock:\n", " ");
+
+ for (i = ([self->attributes count] - 1); i >= 0; i--) {
+ EOAttribute *attr = [self->attributes objectAtIndex:i];
+ BOOL pk, lk, cp, sa;
+
+ pk = _containsObject(self->primaryKeyAttributes, attr);
+ lk = _containsObject(self->attributesUsedForLocking, attr);
+ cp = _containsObject(self->classProperties, attr);
+ sa = (![attr isDerived] && ![attr isFlattened]);
+
+ //NSLog(@"attribute %@ pk=%i lk=%i cp=%i sa=%i", [attr name], pk, lk, cp, sa);
+
+ if ((pk || lk || cp) && (!_containsObject(fetAttr, attr)))
+ [fetAttr addObject:attr];
+
+ if ((pk || lk || cp) && (sa) && (!_containsObject(updAttr, attr))) {
+ [updAttr addObject:attr];
+ [updName addObject:[attr name]];
+ }
+ }
+
+ for (i = [relationships count]-1; i >= 0; i--) {
+ id rel = [relationships objectAtIndex:i];
+
+ if (_containsObject(classProperties, rel))
+ [fetRels addObject:rel];
+ }
+
+ RELEASE(self->attributesUsedForInsert);
+ self->attributesUsedForInsert = [[NSArray alloc] initWithArray:updAttr];
+ RELEASE(self->relationsUsedForFetch);
+ self->relationsUsedForFetch = [[NSArray alloc] initWithArray:fetRels];
+ RELEASE(self->attributesUsedForFetch);
+ self->attributesUsedForFetch =
+ [[NSArray alloc] initWithArray:
+ [fetAttr sortedArrayUsingFunction:_compareByName context:nil]];
+ RELEASE(self->attributesNamesUsedForInsert);
+ attributesNamesUsedForInsert = [updName copy];
+
+ if ([self->attributesUsedForFetch count] == 0) {
+ NSLog(@"WARNING: entity %@ has no fetch attributes: "
+ @"attributes=%@ !",
+ self,
+ [[(id)self->attributes mappedArrayUsingSelector:@selector(name)]
+ componentsJoinedByString:@","]);
+ }
+
+ RELEASE(updAttr); updAttr = nil;
+ RELEASE(fetAttr); fetAttr = nil;
+ RELEASE(fetRels); fetRels = nil;
+ RELEASE(updName); updName = nil;
+
+ self->flags.isPropertiesCacheValid = YES;
+}
+
+- (void)invalidatePropertiesCache {
+ if (flags.isPropertiesCacheValid) {
+ RELEASE(self->attributesUsedForInsert);
+ RELEASE(self->attributesUsedForFetch);
+ RELEASE(self->relationsUsedForFetch);
+ RELEASE(self->attributesNamesUsedForInsert);
+
+ self->attributesUsedForInsert = nil;
+ self->attributesUsedForFetch = nil;
+ self->relationsUsedForFetch = nil;
+ self->attributesNamesUsedForInsert = nil;
+
+ flags.isPropertiesCacheValid = NO;
+ }
+}
+
+// description
+
+- (NSString *)description {
+ return [NSString stringWithFormat:
+ @"<%@[0x%08X]: name=%@ className=%@ tableName=%@ "
+ @"readOnly=%s>",
+ NSStringFromClass([self class]), self,
+ [self name], [self className], [self externalName],
+ [self isReadOnly] ? "YES" : "NO"
+ ];
+}
+
+@end /* EOEntity (EOEntityCreation) */
+
+
+@implementation EOEntity(ValuesConversion)
+
+- (NSDictionary *)convertValuesToModel:(NSDictionary *)aRow {
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ NSEnumerator *enumerator = [aRow keyEnumerator];
+ NSString *key;
+
+ while ((key = [enumerator nextObject])) {
+ id old = [aRow objectForKey:key];
+ id new = [[self attributeNamed:key] convertValueToModel:old];
+
+ if (new) [dict setObject:new forKey:key];
+ }
+
+ return [dict count] ? dict : nil;
+}
+
+static int _compareByName(id obj1, id obj2, void * context) {
+ return [[(EOAttribute*)obj1 name] compare:[(EOAttribute*)obj2 name]];
+}
+
+@end /* EOAttribute (ValuesConversion) */
+
+@implementation EOEntity(EOF2Additions)
+
+- (BOOL)isAbstractEntity {
+ return NO;
+}
+
+/* ids */
+
+- (EOGlobalID *)globalIDForRow:(NSDictionary *)_row {
+ static Class EOKeyGlobalIDClass = Nil;
+ unsigned int keyCount = [self->primaryKeyAttributeNames count];
+ id values[keyCount];
+ unsigned int i;
+
+ for (i = 0; i < keyCount; i++) {
+ NSString *attrName;
+
+ attrName = [self->primaryKeyAttributeNames objectAtIndex:i];
+ values[i] = [_row objectForKey:attrName];
+
+ if (values[i] == nil)
+ return nil;
+ }
+ if (EOKeyGlobalIDClass == Nil) EOKeyGlobalIDClass = [EOKeyGlobalID class];
+
+ return [EOKeyGlobalIDClass globalIDWithEntityName:self->name
+ keys:&(values[0])
+ keyCount:keyCount
+ zone:[self zone]];
+}
+
+- (BOOL)isPrimaryKeyValidInObject:(id)_object {
+ unsigned int keyCount = [self->primaryKeyAttributeNames count];
+ unsigned int i;
+
+ if (_object == nil) return NO;
+
+ for (i = 0; i < keyCount; i++) {
+ if ([_object valueForKey:[self->primaryKeyAttributeNames objectAtIndex:i]]
+ == nil)
+ return NO;
+ }
+ return YES;
+}
+
+/* refs to other models */
+
+- (NSArray *)externalModelsReferenced {
+ NSEnumerator *e;
+ EORelationship *relship;
+ NSMutableArray *result;
+ EOModel *thisModel;
+
+ thisModel = [self model];
+ result = nil;
+
+ e = [self->relationships objectEnumerator];
+ while ((relship = [e nextObject])) {
+ EOEntity *targetEntity;
+ EOModel *extModel;
+
+ targetEntity = [relship destinationEntity];
+ extModel = [targetEntity model];
+
+ if (extModel != thisModel) {
+ if (result == nil) result = [NSMutableArray array];
+ [result addObject:extModel];
+ }
+ }
+ return result ? result : [NSArray array];
+}
+
+/* fetch specs */
+
+- (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name {
+ return nil;
+}
+- (NSArray *)fetchSpecificationNames {
+ return nil;
+}
+
+/* names */
+
+- (void)beautifyName {
+ [self setName:[[self name] _beautifyEntityName]];
+}
+
+@end /* EOEntity(EOF2Additions) */
+
+@implementation EOEntity(PropertyListCoding)
+
+static inline void _addToPropList(NSMutableDictionary *propertyList,
+ id _value, NSString *key) {
+ if (_value) [propertyList setObject:_value forKey:key];
+}
+
+- (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist {
+ int i, count;
+
+ _addToPropList(_plist, self->name, @"name");
+ _addToPropList(_plist, self->className, @"className");
+ _addToPropList(_plist, self->externalName, @"externalName");
+ _addToPropList(_plist, self->externalQuery, @"externalQuery");
+ _addToPropList(_plist, self->userDictionary, @"userDictionary");
+
+ if ((count = [self->attributes count])) {
+ id attributesPList;
+
+ attributesPList = [NSMutableArray array];
+ for (i = 0; i < count; i++) {
+ NSMutableDictionary *attributePList;
+
+ attributePList = [[NSMutableDictionary alloc] init];
+ [[self->attributes objectAtIndex:i]
+ encodeIntoPropertyList:attributePList];
+ [attributesPList addObject:attributePList];
+ RELEASE(attributePList);
+ }
+
+ _addToPropList(_plist, attributesPList, @"attributes");
+ }
+
+ if ((count = [self->attributesUsedForLocking count])) {
+ id attributesUsedForLockingPList;
+
+ attributesUsedForLockingPList = [NSMutableArray array];
+ for (i = 0; i < count; i++) {
+ id attributePList;
+
+ attributePList =
+ [(EOAttribute*)[self->attributesUsedForLocking objectAtIndex:i] name];
+ [attributesUsedForLockingPList addObject:attributePList];
+ }
+ _addToPropList(_plist, attributesUsedForLockingPList,
+ @"attributesUsedForLocking");
+ }
+
+ if ((count = [self->classProperties count])) {
+ id classPropertiesPList = nil;
+
+ classPropertiesPList = [NSMutableArray array];
+ for (i = 0; i < count; i++) {
+ id classPropertyPList;
+
+ classPropertyPList =
+ [(EOAttribute*)[self->classProperties objectAtIndex:i] name];
+ [classPropertiesPList addObject:classPropertyPList];
+ }
+ _addToPropList(_plist, classPropertiesPList, @"classProperties");
+ }
+
+ if ((count = [self->primaryKeyAttributes count])) {
+ id primaryKeyAttributesPList;
+
+ primaryKeyAttributesPList = [NSMutableArray array];
+ for (i = 0; i < count; i++) {
+ id attributePList;
+ attributePList =
+ [(EOAttribute*)[self->primaryKeyAttributes objectAtIndex:i] name];
+ [primaryKeyAttributesPList addObject:attributePList];
+ }
+ _addToPropList(_plist, primaryKeyAttributesPList, @"primaryKeyAttributes");
+ }
+
+ if ((count = [self->relationships count])) {
+ id relationshipsPList;
+
+ relationshipsPList = [NSMutableArray array];
+ for (i = 0; i < count; i++) {
+ NSMutableDictionary *relationshipPList;
+
+ relationshipPList = [NSMutableDictionary dictionary];
+
+ [[self->relationships objectAtIndex:i]
+ encodeIntoPropertyList:relationshipPList];
+ [relationshipsPList addObject:relationshipPList];
+ }
+ _addToPropList(_plist, relationshipsPList, @"relationships");
+ }
+}
+
+@end /* EOEntity(PropertyListCoding) */
+
+@implementation NSString(EntityBeautify)
+
+- (NSString *)_beautifyEntityName {
+ if ([self length] == 0)
+ return @"";
+ else {
+ unsigned clen = 0;
+ char *s = NULL;
+ unsigned cnt, cnt2;
+
+ clen = [self cStringLength];
+#if GNU_RUNTIME
+ s = objc_atomic_malloc(clen + 4);
+#else
+ s = malloc(clen + 4);
+#endif
+
+ [self getCString:s maxLength:clen];
+
+ for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) {
+ if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = toupper(s[cnt + 1]);
+ cnt++;
+ }
+ else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = s[cnt];
+ cnt++;
+ cnt2++;
+ s[cnt2] = toupper(s[cnt]);
+ }
+ else
+ s[cnt2] = tolower(s[cnt]);
+ }
+ s[cnt2] = '\0';
+
+ s[0] = toupper(s[0]);
+
+#if !LIB_FOUNDATION_LIBRARY
+ {
+ NSString *os;
+
+ os = [NSString stringWithCString:s];
+ free(s);
+ return os;
+ }
+#else
+ return [NSString stringWithCStringNoCopy:s freeWhenDone:YES];
+#endif
+ }
+}
+
+@end
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOEntityClassDescription.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#import "EOEntity.h"
+#import "EOAttribute.h"
+#import "EORelationship.h"
+#import <EOControl/EOKeyValueCoding.h>
+#import <EOControl/EOKeyGlobalID.h>
+
+@interface EOClassDescription(ClassDesc)
+/* TODO: check, whether this can be removed */
++ (NSClassDescription *)classDescriptionForEntityName:(NSString *)_entityName;
+@end
+
+@implementation EOEntityClassDescription
+
+- (id)initWithEntity:(EOEntity *)_entity {
+ self->entity = RETAIN(_entity);
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->entity);
+ [super dealloc];
+}
+
+/* creating instances */
+
+- (id)createInstanceWithEditingContext:(id)_ec
+ globalID:(EOGlobalID *)_oid
+ zone:(NSZone *)_zone
+{
+ Class eoClass;
+ id eo;
+
+ eoClass = NSClassFromString([self->entity className]);
+ eo = [eoClass allocWithZone:_zone];
+
+ if ([eo respondsToSelector:
+ @selector(initWithEditingContext:classDescription:globalID:)])
+ eo = [eo initWithEditingContext:_ec classDescription:self globalID:_oid];
+ else
+ eo = [eo init];
+
+ return AUTORELEASE(eo);
+}
+
+/* accessors */
+
+- (EOEntity *)entity {
+ return self->entity;
+}
+
+/* model */
+
+- (NSString *)entityName {
+ return [self->entity name];
+}
+
+- (NSArray *)attributeKeys {
+ NSArray *attrs = [self->entity attributes];
+ unsigned int attrCount = [attrs count];
+ id keys[attrCount];
+ unsigned int i;
+
+ for (i = 0; i < attrCount; i++) {
+ EOAttribute *attribute;
+
+ attribute = [attrs objectAtIndex:i];
+ keys[i] = [attribute name];
+ }
+
+ return [NSArray arrayWithObjects:keys count:attrCount];
+}
+
+- (NSArray *)toManyRelationshipKeys {
+ NSArray *relships = [self->entity relationships];
+ unsigned int attrCount = [relships count];
+ id keys[attrCount];
+ unsigned int i, j;
+
+ for (i = 0, j = 0; i < attrCount; i++) {
+ EORelationship *relship;
+
+ relship = [relships objectAtIndex:i];
+ if ([relship isToMany]) {
+ keys[j] = [relship name];
+ }
+ }
+ return [NSArray arrayWithObjects:keys count:j];
+}
+
+- (NSArray *)toOneRelationshipKeys {
+ NSArray *relships = [self->entity relationships];
+ unsigned int attrCount = [relships count];
+ id keys[attrCount];
+ unsigned int i, j;
+
+ for (i = 0, j = 0; i < attrCount; i++) {
+ EORelationship *relship;
+
+ relship = [relships objectAtIndex:i];
+ if (![relship isToMany]) {
+ keys[j] = [relship name];
+ }
+ }
+ return [NSArray arrayWithObjects:keys count:j];
+}
+
+
+- (NSClassDescription *)classDescriptionForDestinationKey:(NSString *)_key {
+ /* TODO: is this used anywhere?, maybe remove? */
+ EORelationship *relship;
+ NSString *targetEntityName;
+
+ if ((relship = [self->entity relationshipNamed:_key]) == nil)
+ return nil;
+
+ if ([relship isToMany])
+ return nil;
+
+ targetEntityName = [[relship entity] name];
+
+ return [EOClassDescription classDescriptionForEntityName:targetEntityName];
+}
+
+/* validation */
+
+- (NSException *)validateObjectForSave:(id)_object {
+ NSMutableArray *exceptions;
+ NSArray *attrs;
+ unsigned int count, i;
+
+ exceptions = nil;
+
+ /* validate attributes */
+
+ attrs = [self->entity attributes];
+ count = [attrs count];
+
+ for (i = 0; i < count; i++) {
+ EOAttribute *attribute;
+ NSException *exception;
+ id oldValue, newValue;
+
+ attribute = [attrs objectAtIndex:i];
+ oldValue = [_object storedValueForKey:[attribute name]];
+ newValue = oldValue;
+
+ if ((exception = [attribute validateValue:&newValue])) {
+ /* validation failed */
+ if (exceptions == nil) exceptions = [NSMutableArray array];
+ [exceptions addObject:exception];
+ }
+ else if (oldValue != newValue) {
+ /* apply new value to object (value was changed by val-method) */
+ [_object takeStoredValue:newValue forKey:[attribute name]];
+ }
+ }
+
+ /* validate relationships */
+
+ attrs = [self->entity relationships];
+ count = [attrs count];
+
+ for (i = 0; i < count; i++) {
+ EORelationship *relationship;
+ NSException *exception;
+ id oldValue, newValue;
+
+ relationship = [attrs objectAtIndex:i];
+ oldValue = [_object storedValueForKey:[relationship name]];
+ newValue = oldValue;
+
+ if ((exception = [relationship validateValue:&newValue])) {
+ /* validation failed */
+ if (exceptions == nil) exceptions = [NSMutableArray array];
+ [exceptions addObject:exception];
+ }
+ else if (oldValue != newValue) {
+ /* apply new value to object (value was changed by val-method) */
+ [_object takeStoredValue:newValue forKey:[relationship name]];
+ }
+ }
+
+ /* process exceptions */
+
+ if ((count = [exceptions count]) == 0)
+ return nil;
+
+ if (count == 1)
+ return [exceptions objectAtIndex:0];
+
+ {
+ NSException *master;
+ NSMutableDictionary *ui;
+
+ master = [exceptions objectAtIndex:0];
+ ui = [[master userInfo] mutableCopy];
+ if (ui == nil) ui = [[NSMutableDictionary alloc] init];
+ [ui setObject:exceptions forKey:@"EOAdditionalExceptions"];
+
+ master = [NSException exceptionWithName:[master name]
+ reason:[master reason]
+ userInfo:ui];
+ [ui release]; ui = nil;
+ return master;
+ }
+}
+
+@end /* EOEntityClassDescription */
--- /dev/null
+/*
+ EOExpressionArray.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: September 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOExpressionArray.h"
+#import "EOAttribute.h"
+#import "EOEntity.h"
+#import "EORelationship.h"
+
+@implementation EOExpressionArray
+
+- (id)init {
+ [super init];
+ self->array = [[NSMutableArray allocWithZone:[self zone]] init];
+ return self;
+}
+
+- (id)initWithPrefix:(NSString *)_prefix
+ infix:(NSString *)_infix
+ suffix:(NSString *)_suffix
+{
+ [super init];
+ ASSIGN(self->prefix, _prefix);
+ ASSIGN(self->infix, _infix);
+ ASSIGN(self->suffix, _suffix);
+ RELEASE(self->array);
+ self->array = [[NSMutableArray allocWithZone:[self zone]] init];
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->array);
+ RELEASE(self->prefix);
+ RELEASE(self->infix);
+ RELEASE(self->suffix);
+ [super dealloc];
+}
+
+- (BOOL)referencesObject:(id)anObject {
+ return [self indexOfObject:anObject] != NSNotFound;
+}
+
+- (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
+ if(ctx && [self count] &&
+ [[self objectAtIndex:0] isKindOfClass:[EORelationship class]])
+ return [ctx expressionValueForAttributePath:self->array];
+ else {
+ int i, count;
+ id result;
+ SEL sel;
+ IMP imp;
+
+ count = [self count];
+ result = [NSMutableString stringWithCapacity:256];
+ sel = @selector(appendString:);
+ imp = [result methodForSelector:sel];
+
+ if (self->prefix)
+ [result appendString:self->prefix];
+
+ if (count) {
+ id o;
+
+ o = [self objectAtIndex:0];
+
+ (*imp)(result, sel, [o expressionValueForContext:ctx]);
+ for (i = 1 ; i < count; i++) {
+ if (self->infix)
+ (*imp)(result, sel, self->infix);
+
+ o = [self objectAtIndex:i];
+ (*imp)(result, sel, [o expressionValueForContext:ctx]);
+ }
+ }
+
+ if (self->suffix)
+ [result appendString:self->suffix];
+
+ return result;
+ }
+}
+
+- (void)setPrefix:(NSString *)_prefix {
+ ASSIGN(self->prefix, _prefix);
+}
+- (void)setInfix:(NSString *)_infix {
+ ASSIGN(self->infix, _infix);
+}
+- (void)setSuffix:(NSString *)_suffix {
+ ASSIGN(self->suffix, _suffix);
+}
+
+- (NSString *)prefix {
+ return self->prefix;
+}
+- (NSString *)infix {
+ return self->infix;
+}
+- (NSString *)suffix {
+ return self->suffix;
+}
+
++ (EOExpressionArray *)parseExpression:(NSString *)expression
+ entity:(EOEntity *)entity
+ replacePropertyReferences:(BOOL)replacePropertyReferences
+{
+ return [EOExpressionArray parseExpression:expression
+ entity:entity
+ replacePropertyReferences:
+ replacePropertyReferences
+ relationshipPaths:nil];
+}
+
++ (EOExpressionArray *)parseExpression:(NSString *)expression
+ entity:(EOEntity *)entity
+ replacePropertyReferences:(BOOL)replacePropertyReferences
+ relationshipPaths:(NSMutableArray *)relationshipPaths
+{
+ EOExpressionArray *exprArray;
+ unsigned char buf[[expression cStringLength] + 4]; // TODO: not too good
+ const unsigned char *s, *start;
+ id objectToken;
+ NSAutoreleasePool *pool;
+
+ exprArray = [[EOExpressionArray new] autorelease];
+ pool = [[NSAutoreleasePool alloc] init];
+ [expression getCString:buf];
+ s = buf;
+
+ /* Divide the expression string in alternating substrings that obey the
+ following simple grammar:
+
+ I = [a-zA-Z0-9@_#]([a-zA-Z0-9@_.#$])+
+ O = \'.*\' | \".*\" | [^a-zA-Z0-9@_#]+
+ S -> I S | O S | nothing
+ */
+ while(*s) {
+ /* Determines an I token. */
+ if(isalnum((int)*s) || *s == '@' || *s == '_' || *s == '#') {
+ start = s;
+ for(++s; *s; s++)
+ if(!isalnum((int)*s) && *s != '@' && *s != '_'
+ && *s != '.' && *s != '#' && *s != '$')
+ break;
+
+ objectToken = [NSString stringWithCString:start
+ length:(unsigned)(s - start)];
+ if (replacePropertyReferences) {
+ id property = [entity propertyNamed:objectToken];
+ if(property) {
+ if ([objectToken isNameOfARelationshipPath] &&
+ relationshipPaths) {
+ [relationshipPaths addObject:
+ [entity relationshipsNamed:
+ objectToken]];
+ }
+ objectToken = property;
+ }
+ }
+ [exprArray addObject:objectToken];
+ }
+
+ /* Determines an O token. */
+ start = s;
+ for(; *s && !isalnum((int)*s) && *s != '@' && *s != '_' && *s != '#';
+ s++) {
+ if(*s == '\'' || *s == '"') {
+ unsigned char quote = *s;
+
+ for(++s; *s; s++)
+ if(*s == quote)
+ break;
+ else if(*s == '\\')
+ s++; /* Skip the escaped characters */
+ if(!*s) {
+ [NSException raise:@"SyntaxErrorException"
+ format:@"unterminated character string"];
+ }
+ }
+ }
+ if (s != start) {
+ objectToken = [NSString stringWithCString:start
+ length:(unsigned)(s - start)];
+ [exprArray addObject:objectToken];
+ }
+ }
+
+ RELEASE(pool);
+ return exprArray;
+}
+
+/* NSMutableCopying */
+
+- (id)copyWithZone:(NSZone *)_zone {
+ return [self mutableCopyWithZone:_zone];
+}
+- (id)mutableCopyWithZone:(NSZone *)_zone {
+ EOExpressionArray *new;
+
+ new = [[EOExpressionArray allocWithZone:_zone]
+ initWithPrefix:self->prefix
+ infix:self->infix
+ suffix:self->suffix];
+ RELEASE(new->array); new->array = nil;
+ new->array = [self->array mutableCopyWithZone:_zone];
+
+ return new;
+}
+
+/* NSArray compatibility */
+
+- (void)addObjectsFromExpressionArray:(EOExpressionArray *)_array {
+ [self->array addObjectsFromArray:_array->array];
+}
+
+- (void)insertObject:(id)_obj atIndex:(unsigned int)_idx {
+ [self->array insertObject:_obj atIndex:_idx];
+}
+- (void)addObjectsFromArray:(NSArray *)_array {
+ [self->array addObjectsFromArray:_array];
+}
+
+- (void)addObject:(id)_object {
+ [self->array addObject:_object];
+}
+
+- (unsigned int)indexOfObject:(id)_object {
+ return [self->array indexOfObject:_object];
+}
+
+- (id)objectAtIndex:(unsigned int)_idx {
+ return [self->array objectAtIndex:_idx];
+}
+- (id)lastObject {
+ return [self->array lastObject];
+}
+- (unsigned int)count {
+ return [self->array count];
+}
+
+- (NSEnumerator *)objectEnumerator {
+ return [self->array objectEnumerator];
+}
+- (NSEnumerator *)reverseObjectEnumerator {
+ return [self->array reverseObjectEnumerator];
+}
+
+- (NSString *)description {
+ NSMutableString *ms;
+
+ ms = [NSMutableString stringWithCapacity:128];
+ [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+
+ if (self->array) [ms appendFormat:@" array=%@", self->array];
+ if (self->prefix) [ms appendFormat:@" prefix='%@'", self->prefix];
+ if (self->infix) [ms appendFormat:@" infix='%@'", self->infix];
+ if (self->suffix) [ms appendFormat:@" suffix='%@'", self->suffix];
+
+ [ms appendString:@">"];
+ return ms;
+}
+
+@end /* EOExpressionArray */
+
+@implementation NSObject(EOExpression)
+
+- (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
+ if([self respondsToSelector:@selector(stringValue)])
+ return [(id)self stringValue];
+
+ return [self description];
+}
+
+@end /* NSObject(EOExpression) */
+
+@implementation NSString(EOExpression)
+
+/*
+ Avoid returning the description in case of NSString because if the string
+ contains whitespaces it will be quoted. Particular adaptors have to override
+ -formatValue:forAttribute: and they have to quote with the specific
+ database character the returned string.
+*/
+- (NSString *)expressionValueForContext:(id<EOExpressionContext>)ctx {
+ return self;
+}
+
+@end /* NSString(EOExpression) */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ EOFExceptions.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOFExceptions.h"
+#import "EOEntity.h"
+#import "EORelationship.h"
+
+@implementation EOFException
+@end /* EOFException */
+
+
+@implementation ObjectNotAvailableException
+
+- initWithEntity:entity andPrimaryKey:key {
+ id _reason = [NSString stringWithFormat:@"A to-one relation could not be "
+ @"resolved for entity %@ and primary key %@",
+ [(EOEntity*)entity name], [key description]];
+
+ [self initWithName:@"NSObjectNotAvailableException"
+ reason:_reason userInfo:nil];
+ return self;
+}
+
+@end /* ObjectNotAvailableException */
+
+
+@implementation PropertyDefinitionException
+@end /* PropertyDefinitionException */
+
+
+@implementation DestinationEntityDoesntMatchDefinitionException
+
+- initForDestination:(EOEntity*)destinationEntity
+ andDefinition:(NSString*)definition
+ relationship:(EORelationship*)relationship
+{
+ id _reason = [NSString stringWithFormat:@"destination entity '%@' does not"
+ @" match definition '%@' in relationship '%@'",
+ [destinationEntity name],
+ definition,
+ [relationship name]];
+ [self initWithName:NSStringFromClass(isa)
+ reason:_reason userInfo:nil];
+ return self;
+}
+@end /* DestinationEntityDoesntMatchDefinitionException */
+
+
+@implementation InvalidNameException
+- initWithName:(NSString*)_name
+{
+ id _reason = [NSString stringWithFormat:@"invalid name: '%@'", _name];
+ [self initWithName:NSStringFromClass(isa) reason:_reason userInfo:nil];
+ return self;
+}
+@end /* InvalidNameException */
+
+
+@implementation InvalidPropertyException
+- initWithName:propertyName entity:currentEntity
+{
+ id _reason = [NSString stringWithFormat:@"property '%@' does not exist in "
+ @"entity '%@'", propertyName,
+ [(EOEntity*)currentEntity name]];
+ [self initWithName:NSStringFromClass(isa)
+ reason:_reason userInfo:nil];
+ return self;
+}
+@end /* InvalidPropertyException */
+
+
+@implementation RelationshipMustBeToOneException
+- initWithName:propertyName entity:currentEntity
+{
+ id _reason = [NSString stringWithFormat:@"property '%@' must be to one in "
+ @"entity '%@' to allow flattened attribute",
+ propertyName, [(EOEntity*)currentEntity name]];
+ [self initWithName:NSStringFromClass(isa)
+ reason:_reason userInfo:nil];
+ return self;
+}
+@end /* RelationshipMustBeToOneException */
+
+
+@implementation InvalidValueTypeException
+- initWithType:type
+{
+ id _reason = [NSString stringWithFormat:@"unknow value type '%@'", type];
+ [self initWithName:@"InvalidValueTypeException"
+ reason:_reason userInfo:nil];
+ return self;
+}
+@end
+
+
+@implementation InvalidAttributeException
+@end /* InvalidAttributeException */
+
+
+@implementation InvalidQualifierException
+@end /* InvalidQualifierException */
+
+
+@implementation EOAdaptorException
+@end /* EOAdaptorException */
+
+
+@implementation CannotFindAdaptorBundleException
+@end /* CannotFindAdaptorBundleException */
+
+
+@implementation InvalidAdaptorBundleException
+@end /* InvalidAdaptorBundleException */
+
+
+@implementation InvalidAdaptorStateException
++ exceptionWithAdaptor:(id)_adaptor
+{
+ InvalidAdaptorStateException* exception = [self alloc];
+ exception->adaptor = _adaptor;
+ return exception;
+}
+@end /* InvalidAdaptorStateException */
+
+
+@implementation DataTypeMappingNotSupportedException
+@end /* DataTypeMappingNotSupportedException */
+
+
+@implementation ChannelIsNotOpenedException
+@end /* ChannelIsNotOpenedException */
+
+
+@implementation AdaptorIsFetchingException
+@end /* AdaptorIsFetchingException */
+
+
+@implementation AdaptorIsNotFetchingException
+@end /* AdaptorIsNotFetchingException */
+
+
+@implementation NoTransactionInProgressException
+@end /* NoTransactionInProgressException */
+
+
+@implementation TooManyOpenedChannelsException
+@end /* TooManyOpenedChannelsException */
--- /dev/null
+/*
+ EOAttributeOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// $Id: EOFault.m 1 2004-08-20 10:38:46Z znek $
+
+#include "EOFault.h"
+#include "EOFaultHandler.h"
+#include "common.h"
+
+#if NeXT_RUNTIME || APPLE_RUNTIME
+# include <objc/objc-class.h>
+#endif
+
+typedef struct {
+ Class isa;
+} *my_objc_object;
+
+#if GNU_RUNTIME
+# define object_is_instance(object) \
+ ((object!=nil)&&CLS_ISCLASS(((my_objc_object)object)->isa))
+#else
+# warning TODO: implement for NeXT/Apple runtime!
+# define object_is_instance(object) (object!=nil?YES:NO)
+#endif
+
+
+/*
+ * EOFault class
+ */
+
+@implementation EOFault
+
++ (void)makeObjectIntoFault:(id)_object withHandler:(EOFaultHandler *)_handler {
+ [_handler setTargetClass:[_object class] extraData:((id *)_object)[1]];
+
+ ((EOFault *)_object)->isa = self;
+ ((EOFault *)_object)->faultResolver = [_handler retain];
+}
+
++ (EOFaultHandler *)handlerForFault:(id)_fault {
+ if (![self isFault:_fault])
+ return nil;
+
+ return ((EOFault *)_fault)->faultResolver;
+}
+
+/* Fault class methods */
+
++ (void)clearFault:(id)fault {
+ EOFault *aFault = (EOFault*)fault;
+ int refs;
+
+ /* check if fault */
+ if (aFault->isa != self)
+ return;
+
+ /* get fault instance reference count + 1 set in creation methods */
+ refs = aFault->faultResolver->faultReferences;
+
+ /* make clear instance */
+ aFault->isa = [aFault->faultResolver targetClass];
+ aFault->faultResolver = [aFault->faultResolver autorelease];
+ aFault->faultResolver = [aFault->faultResolver extraData];
+
+ /*
+ set references to real instance so that
+ re-implemented retain/release mechanism take control
+ */
+ while(refs-- > 0)
+ [aFault retain];
+}
+
++ (BOOL)isFault:(id)fault {
+ static Class EOFaultClass = Nil;
+ Class clazz;
+
+ if (fault == nil) return NO;
+ if (EOFaultClass == Nil) EOFaultClass = [EOFault class];
+
+ for (clazz = ((EOFault *)fault)->isa; clazz; clazz = clazz->super_class) {
+ if (clazz == EOFaultClass)
+ return YES;
+ }
+ return NO;
+}
++ (BOOL)isFault {
+ return NO; // no class faults
+}
+- (BOOL)isFault {
+ return YES;
+}
+
++ (Class)targetClassForFault:(id)_fault {
+ EOFault *aFault = (EOFault*)_fault;
+
+ // Check that argument is fault
+ if (aFault->isa != self)
+ return nil;
+
+ return [aFault->faultResolver targetClass];
+}
+
+// Fault Instance methods
+
+- (Class)superclass {
+#if GNU_RUNTIME
+ return (object_is_instance(self))
+ ? [[self->faultResolver classForFault:self] superclass]
+ : class_get_super_class((Class)self);
+#else
+# warning TODO: add complete implementation for NeXT/Apple runtime!
+ return [[self->faultResolver classForFault:self] superclass];
+#endif
+}
+
++ (Class)class {
+ return self;
+}
+- (Class)class {
+ return [self->faultResolver classForFault:self];
+}
+
+- (BOOL)isKindOfClass:(Class)_class; {
+ return [self->faultResolver isKindOfClass:_class forFault:self];
+}
+- (BOOL)isMemberOfClass:(Class)_class {
+ return [self->faultResolver isMemberOfClass:_class forFault:self];
+}
+
+- (BOOL)conformsToProtocol:(Protocol *)_protocol {
+ return [self->faultResolver conformsToProtocol:_protocol forFault:self];
+}
+
++ (BOOL)respondsToSelector:(SEL)_selector {
+#if GNU_RUNTIME
+ return class_get_instance_method(self, _selector) != NULL;
+#else
+# warning TODO: add complete implementation for Apple/NeXT runtime!
+ return NO;
+#endif
+}
+
+- (BOOL)respondsToSelector:(SEL)_selector {
+#if GNU_RUNTIME
+ return (object_is_instance(self))
+ ? [self->faultResolver respondsToSelector:_selector forFault:self]
+ : class_get_class_method(self->isa, _selector) != METHOD_NULL;
+#else
+# warning TODO: add complete implementation for Apple/NeXT runtime!
+ return [self->faultResolver respondsToSelector:_selector forFault:self];
+#endif
+}
+
+// ******************** retain counting ********************
+
++ (id)retain {
+ return self;
+}
+- (id)retain {
+ self->faultResolver->faultReferences++;
+ return self;
+}
+
++ (oneway void)release {
+}
+- (oneway void)release {
+ if (faultResolver->faultReferences <= 0)
+ [self dealloc];
+ else
+ faultResolver->faultReferences--;
+}
+
++ (unsigned)retainCount {
+ return 1;
+}
+- (unsigned)retainCount {
+ // For instance
+ return faultResolver->faultReferences+1;
+}
+
++ (id)autorelease {
+ return self;
+}
+- (id)autorelease {
+ [NSAutoreleasePool addObject:self];
+ return self;
+}
+
+- (NSZone *)zone {
+ return NSZoneFromPointer(self);
+}
+
+- (BOOL)isProxy {
+ return NO;
+}
+- (BOOL)isGarbageCollectable {
+ return NO;
+}
+
++ (void)dealloc {
+ NSLog(@"WARNING: tried to deallocate EOFault class ..");
+}
+- (void)dealloc {
+ [self->isa clearFault:self];
+ [self dealloc];
+}
+
+/* descriptions */
+
+- (NSString *)description {
+ return [self->faultResolver descriptionForObject:self];
+}
+- (NSString *)descriptionWithIndent:(unsigned)level {
+ return [self description];
+}
+- (NSString *)stringRepresentation {
+ return [self description];
+}
+- (NSString *)eoShallowDescription {
+ return [self description];
+}
+
+- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
+ indent:(int)_i
+{
+ return [self description];
+}
+
+/* Forwarding stuff */
+
++ (void)initialize {
+ /*
+ Must be here as initialize is called for each root class
+ without asking if it responds to it !
+ */
+}
+
+static inline void _resolveFault(EOFault *self) {
+ EOFaultHandler *handler;
+
+ /* If in class */
+ if (!object_is_instance(self)) {
+ [NSException raise:@"NSInvalidArgumentException"
+ format:@"used EOFault class in forward"];
+ }
+
+ handler = self->faultResolver;
+ [handler completeInitializationOfObject:self];
+
+ if (self->isa == [EOFault class]) {
+ [NSException raise:@"NSInvalidArgumentException"
+ format:
+ @"fault error: %@ was not cleared during fault fetching",
+ [handler descriptionForObject:self]];
+ }
+}
+
++ (id)self {
+ _resolveFault(self);
+ return self;
+}
+
+#if 0
+
+- (void)setObject:(id)object forKey:(id)key {
+ _resolveFault(self);
+ [self setObject:object forKey:key];
+}
+- (id)objectForKey:(id)key {
+ _resolveFault(self);
+ return [self objectForKey:key];
+}
+- (void)removeObjectForKey:(id)key {
+ _resolveFault(self);
+ [self removeObjectForKey:key];
+}
+
+- (void)takeValuesFromDictionary:(NSDictionary *)dictionary {
+ _resolveFault(self);
+ [self takeValuesFromDictionary:dictionary];
+}
+- (NSDictionary *)valuesForKeys:(NSArray *)keys {
+ _resolveFault(self);
+ return [self valuesForKeys:keys];
+}
+- (BOOL)takeValue:(id)object forKey:(id)key {
+ _resolveFault(self);
+ return [self takeValue:object forKey:key];
+}
+- (id)valueForKey:(id)key {
+ _resolveFault(self);
+ return [self valueForKey:key];
+}
+
+- (BOOL)kvcIsPreferredInKeyPath {
+ _resolveFault(self);
+ return YES;
+}
+
+#endif /* 0 */
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)_sel {
+ return [self->faultResolver methodSignatureForSelector:_sel forFault:self];
+}
+
+- (void)forwardInvocation:(NSInvocation *)_invocation {
+ if ([self->faultResolver shouldPerformInvocation:_invocation]) {
+ _resolveFault(self);
+ [_invocation invoke];
+ }
+}
+
+@end /* EOFault */
+
+@implementation EOFault(RealForwarding)
+
+#if NeXT_Foundation_LIBRARY
+
+- (void)forwardInvocation:(NSInvocation *)_inv {
+ _resolveFault(self);
+
+ [_inv setTarget:self];
+ [_inv invoke];
+}
+
+#else
+
+- (retval_t)forward:(SEL)sel:(arglist_t)args {
+#if 1 && !defined(__APPLE__)
+ Method_t forward;
+
+ forward = class_get_instance_method(objc_lookup_class("NSObject"), _cmd);
+ return ((retval_t (*)(id, SEL, SEL, arglist_t))forward->method_imp)
+ (self, _cmd, sel, args);
+#else
+ struct objc_method *m;
+
+ _resolveFault(self);
+
+ if ((m = class_get_instance_method(self->isa, sel)) == NULL) {
+ NSString *r;
+
+ r = [NSString stringWithFormat:
+ @"fault error: resolved fault does not responds to selector %s",
+ sel_get_name(sel)];
+ [NSException raise:@"NSInvalidArgumentException" reason:r userInfo:nil];
+ }
+ return objc_msg_sendv(self, sel, args);
+#endif
+}
+#endif
+
+@end /* EOFault(RealForwarding) */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOFaultHandler.m 1 2004-08-20 10:38:46Z znek $
+
+#include "EOFaultHandler.h"
+#include "EOFault.h"
+#include "common.h"
+
+#if NeXT_RUNTIME
+# if !defined(METHOD_NULL)
+# define METHOD_NULL NULL
+# endif
+#endif
+
+@implementation EOFaultHandler
+
+- (void)setTargetClass:(Class)_class extraData:(void *)_extraData {
+ self->targetClass = _class;
+ self->extraData = _extraData;
+}
+
+- (Class)targetClass; {
+ return self->targetClass;
+}
+- (void *)extraData {
+ return self->extraData;
+}
+
+/* firing */
+
+- (BOOL)shouldPerformInvocation:(NSInvocation *)_invocation {
+ return YES;
+}
+
+- (void)faultWillFire:(EOFault *)_fault {
+}
+
+- (void)completeInitializationOfObject:(id)_object {
+ [self doesNotRecognizeSelector:_cmd];
+}
+
+/* fault reflection */
+
+- (Class)classForFault:(EOFault *)_fault {
+#if GNU_RUNTIME
+ return (object_is_instance(_fault))
+ ? [self targetClass]
+ : (*(Class *)_fault);
+#else
+# warning TODO: add complete implementation for Apple/NeXT runtime!
+ return [self targetClass];
+#endif
+}
+
+- (BOOL)respondsToSelector:(SEL)_selector forFault:(EOFault *)_fault {
+ Class class;
+
+ /* first check whether fault itself responds to selector */
+#if GNU_RUNTIME
+ if (class_get_instance_method(*(Class *)_fault, _selector) != METHOD_NULL)
+ return YES;
+#else
+# warning TODO: add implementation for NeXT/Apple runtime!
+#endif
+
+ /* then check whether the target class does */
+ class = [self targetClass];
+#if GNU_RUNTIME
+ return (class_get_instance_method(class, _selector) != NULL) ? YES : NO;
+#else
+# warning TODO: use NeXT/Apple runtime function
+ return [class methodForSelector:_selector] ? YES : NO;
+#endif
+}
+
+- (BOOL)conformsToProtocol:(Protocol *)_protocol forFault:(EOFault *)_fault {
+ Class class, sClass;
+
+#if GNU_RUNTIME
+ struct objc_protocol_list* protos;
+ int i;
+
+ class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault;
+ for (protos = class->protocols; protos; protos = protos->next) {
+ for (i = 0; i < protos->count; i++) {
+ if ([protos->list[i] conformsTo:_protocol])
+ return YES;
+ }
+ }
+#else
+# warning TODO: implement on NeXT/Apple runtime!
+ class = [self targetClass];
+#endif
+
+ return ((sClass = [class superclass]))
+ ? [sClass conformsToProtocol:_protocol]
+ : NO;
+}
+
+- (BOOL)isKindOfClass:(Class)_class forFault:(EOFault *)_fault {
+ Class class;
+
+#if GNU_RUNTIME
+ class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault;
+ for (; class != Nil; class = class_get_super_class(class)) {
+ if (class == _class)
+ return YES;
+ }
+#else
+# warning TODO: add implementation for NeXT/Apple runtime!
+ class = [self targetClass];
+#endif
+ return NO;
+}
+
+- (BOOL)isMemberOfClass:(Class)_class forFault:(EOFault *)_fault {
+ Class class;
+#if GNU_RUNTIME
+ class = object_is_instance(_fault) ? [self targetClass] : (Class)_fault;
+#else
+# warning TODO: add implementation for NeXT/Apple runtime!
+ class = [self targetClass];
+#endif
+ return class == _class ? YES : NO;
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector
+ forFault:(EOFault *)_fault
+{
+#if NeXT_Foundation_LIBRARY
+ // probably incorrect
+ return [_fault methodSignatureForSelector:_selector];
+#else
+ register const char *types = NULL;
+
+ if (_selector == NULL) // invalid selector
+ return nil;
+
+#if GNU_RUNTIME && 0
+ // GNU runtime selectors may be typed, a lookup may not be necessary
+ types = aSelector->sel_types;
+#endif
+
+ /* first check for EOFault's own methods */
+
+ if (types == NULL) {
+ // lookup method for selector
+ struct objc_method *mth;
+ mth = class_get_instance_method(*(Class *)_fault, _selector);
+ if (mth) types = mth->method_types;
+ }
+
+ /* then check in target class methods */
+
+ if (types == NULL) {
+ // lookup method for selector
+ struct objc_method *mth;
+ mth = class_get_instance_method([self targetClass], _selector);
+ if (mth) types = mth->method_types;
+ }
+
+#if GNU_RUNTIME
+ // GNU runtime selectors may be typed, a lookup may not be necessary
+ if (types == NULL)
+ types = _selector->sel_types;
+#endif
+ if (types == NULL)
+ return nil;
+
+ return [NSMethodSignature signatureWithObjCTypes:types];
+#endif
+}
+
+/* description */
+
+- (NSString *)descriptionForObject:(id)_fault {
+ return [NSString stringWithFormat:@"<%@[0x%08X]: on=%@>",
+ NSStringFromClass(*(Class *)_fault),
+ _fault,
+ NSStringFromClass([self targetClass])];
+}
+
+@end /* EOFaultHandler */
--- /dev/null
+/*
+ EOGenericRecord.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSMapTable.h>
+#import <Foundation/NSArray.h>
+#import "common.h"
+#import "EOEntity.h"
+#import "EOGenericRecord.h"
+#import "EODatabase.h"
+#import <GDLAccess/EOFault.h>
+#import <EOControl/EOClassDescription.h>
+
+@interface EOClassDescription(ClassDesc)
+/* TODO: check, whether this can be removed */
++ (NSClassDescription *)classDescriptionForEntityName:(NSString *)_entityName;
+@end
+
+@implementation EOGenericRecord(EOAccess)
+
+- (id)initWithPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity {
+ /* TODO: is this method ever used? Maybe remove */
+ EOClassDescription *cd;
+ NSEnumerator *e;
+ NSString *key;
+
+ if (_entity == nil) {
+ AUTORELEASE(self);
+ NSLog(@"WARNING: tried to create generic record with <nil> entity !");
+ return nil;
+ }
+
+ cd = (id)[EOClassDescription classDescriptionForEntityName:[_entity name]];
+#if DEBUG
+ NSAssert1(cd, @"did not find class description for entity %@", _entity);
+#endif
+
+ self = [self initWithEditingContext:nil
+ classDescription:cd
+ globalID:nil];
+
+ e = [_key keyEnumerator];
+
+ while ((key = [e nextObject]))
+ [self setObject:[_key objectForKey:key] forKey:key];
+
+ return self;
+}
+
+- (void)_letDatabasesForget {
+ [EODatabase forgetObject:self];
+}
+
+/* model */
+
+- (EOEntity *)entity {
+ return [(EOEntityClassDescription *)[self classDescription] entity];
+}
+
+@end /* EOGenericRecord(EOAccess) */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOKeyComparisonQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $
+
+#import "EOSQLQualifier.h"
+#include "common.h"
+
+#if NeXT_RUNTIME || APPLE_RUNTIME
+# ifndef SEL_EQ
+# define SEL_EQ(__A__,__B__) (__A__==__B__?YES:NO)
+# endif
+#endif
+
+@implementation EOKeyComparisonQualifier(SQLQualifier)
+
+/* SQL qualifier generation */
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity {
+ EOSQLQualifier *q;
+ NSString *format;
+
+ if (SEL_EQ(self->operator, EOQualifierOperatorEqual))
+ format = @"%A = %A";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorNotEqual))
+ format = @"%A <> %A";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorLessThan))
+ format = @"%A < %A";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorGreaterThan))
+ format = @"%A > %A";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorLessThanOrEqualTo))
+ format = @"%A <= %A";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorGreaterThanOrEqualTo))
+ format = @"%A >= %A";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorLike))
+ format = @"%A LIKE %A";
+ else {
+ format = [NSString stringWithFormat:@"%%A %@ %%A",
+ NSStringFromSelector(self->operator)];
+ }
+
+ q = [[EOSQLQualifier alloc]
+ initWithEntity:_entity
+ qualifierFormat:format, self->leftKey, self->rightKey];
+ return AUTORELEASE(q);
+}
+
+@end /* EOKeyComparisonQualifier(SQLQualifier) */
--- /dev/null
+/*
+ EOKeySortOrdering.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import <Foundation/NSAutoreleasePool.h>
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSString.h>
+#import "common.h"
+#import "EOKeySortOrdering.h"
+#import <EOControl/EOKeyValueCoding.h>
+
+@implementation EOKeySortOrdering
+
++ keyOrderingWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering
+{
+ return AUTORELEASE([[EOKeySortOrdering alloc]
+ initWithKey:aKey ordering:anOrdering]);
+}
+
+- initWithKey:(NSString*)aKey ordering:(NSComparisonResult)anOrdering
+{
+ ASSIGN(key, aKey);
+ ordering = anOrdering;
+ return self;
+}
+
+- (NSString*)key {return key;}
+- (NSComparisonResult)ordering {return ordering;}
+
+@end
+
+// TODO : integrate this function in the two methods above and optimize
+// object creation and method calls for objects that provide quick
+// access to their values - do not use nested functions
+
+static NSComparisonResult _keySortCompare(id obj1, id obj2, NSArray* order)
+ __attribute__((unused));
+
+static NSComparisonResult _keySortCompare(id obj1, id obj2, NSArray* order) {
+ int i, n;
+
+ for (i = 0, n = [order count]; i < n; i++) {
+ id val1, val2, key, kar;
+ NSComparisonResult ord, vord;
+ EOKeySortOrdering* kso = [order objectAtIndex:i];
+
+ key = [kso key];
+ ord = [kso ordering];
+ kar = [NSArray arrayWithObject:key];
+
+ val1 = [[obj1 valuesForKeys:kar] objectForKey:key];
+ val2 = [[obj2 valuesForKeys:kar] objectForKey:key];
+
+ if (!val1 && !val2)
+ continue;
+
+ if (!val1 && val2)
+ return ord == NSOrderedAscending ?
+ NSOrderedAscending : NSOrderedDescending;
+
+ if (val1 && !val2)
+ return ord == NSOrderedAscending ?
+ NSOrderedDescending : NSOrderedAscending;
+
+ vord = [(NSString *)val1 compare:val2];
+
+ if (vord == NSOrderedSame)
+ continue;
+
+ if (vord == NSOrderedAscending)
+ return ord == NSOrderedAscending ?
+ NSOrderedAscending : NSOrderedDescending;
+ else
+ return ord == NSOrderedAscending ?
+ NSOrderedDescending : NSOrderedAscending;
+ }
+
+ return NSOrderedSame;
+}
+
+#if 0
+
+@implementation NSArray(EOKeyBasedSorting)
+
+- (NSArray*)sortedArrayUsingKeyOrderArray:(NSArray*)orderArray
+{
+ NSArray* arry;
+ CREATE_AUTORELEASE_POOL(pool);
+
+ arry = [self sortedArrayUsingFunction:
+ (int(*)(id, id, void*))_keySortCompare
+ context:orderArray];
+ RELEASE(pool);
+ return arry;
+}
+
+@end
+
+@implementation NSMutableArray(EOKeyBasedSorting)
+
+- (void)sortUsingKeyOrderArray:(NSArray*)orderArray
+{
+ CREATE_AUTORELEASE_POOL(pool);
+
+ [self sortUsingFunction:
+ (int(*)(id, id, void*))_keySortCompare
+ context:orderArray];
+ RELEASE(pool);
+}
+
+@end
+
+#endif
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
+
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOKeyValueQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $
+
+#import "EOSQLQualifier.h"
+#include "common.h"
+
+@implementation EOKeyValueQualifier(SQLQualifier)
+
+/* SQL qualifier generation */
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity {
+ EOSQLQualifier *q;
+ NSString *format;
+
+ if (SEL_EQ(self->operator, EOQualifierOperatorEqual))
+ format = @"%A = %@";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorNotEqual))
+ format = @"%A <> %@";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorLessThan))
+ format = @"%A < %@";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorGreaterThan))
+ format = @"%A > %@";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorLessThanOrEqualTo))
+ format = @"%A <= %@";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorGreaterThanOrEqualTo))
+ format = @"%A >= %@";
+ else if (SEL_EQ(self->operator, EOQualifierOperatorLike))
+ format = @"%A LIKE %@";
+ else {
+ format = [NSString stringWithFormat:@"%%A %@ %%@",
+ NSStringFromSelector(self->operator)];
+ }
+
+ q = [[EOSQLQualifier alloc]
+ initWithEntity:_entity
+ qualifierFormat:format, self->key, self->value];
+ return AUTORELEASE(q);
+}
+
+@end /* EOKeyValueQualifier */
--- /dev/null
+/*
+ EOModel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOModel.h"
+#import "EOEntity.h"
+
+/* Include the code from EOKeyValueCoding.m and EOCustomValues.m here because
+ they contain categories to various classes from Foundation that don't get
+ linked into the client application since no one refers them. The NeXT linker
+ knows how to deal with this but all the other linkers don't... */
+#if 0
+# import "EOCustomValues.m"
+#endif
+
+void EOModel_linkCategories(void) {
+ void EOAccess_EOCustomValues_link(void);
+
+ EOAccess_EOCustomValues_link();
+}
+
+@implementation EOModel
+
+- (id)copyWithZone:(NSZone *)_zone {
+ return RETAIN(self);
+}
+
++ (NSString*)findPathForModelNamed:(NSString*)modelName {
+ int i;
+ NSBundle* bundle = [NSBundle mainBundle];
+ NSString* modelPath = [bundle pathForResource:modelName ofType:@"eomodel"];
+ NSString* paths[] = { @"~/Library/Models",
+ @"/LocalLibrary/Models",
+ @"/NextLibrary/Models",
+ nil };
+
+ if(modelPath)
+ return modelPath;
+
+ for(i = 0; paths[i]; i++) {
+ bundle = [NSBundle bundleWithPath:paths[i]];
+ modelPath = [bundle pathForResource:modelName ofType:@"eomodel"];
+ if(modelPath)
+ return modelPath;
+ }
+ return nil;
+}
+
+- (id)init {
+ if ((self = [super init])) {
+ NSNotificationCenter *nc;
+
+ nc = [NSNotificationCenter defaultCenter];
+ [nc addObserver:self selector:@selector(_requireClassDescriptionForClass:)
+ name:@"EOClassDescriptionNeededForClass" object:nil];
+ [nc addObserver:self
+ selector:@selector(_requireClassDescriptionForEntityName:)
+ name:@"EOClassDescriptionNeededForEntityName" object:nil];
+
+ self->entities = [[NSArray alloc] init];
+ self->entitiesByName = [[NSMutableDictionary alloc] initWithCapacity:4];
+ self->entitiesByClassName =
+ [[NSMutableDictionary alloc] initWithCapacity:4];
+ }
+
+ return self;
+}
+
+- (void)resetEntities {
+ [self->entities makeObjectsPerformSelector:@selector(resetModel)];
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [self resetEntities];
+ RELEASE(self->entities);
+ RELEASE(self->entitiesByName);
+ RELEASE(self->entitiesByClassName);
+ RELEASE(self->name);
+ RELEASE(self->path);
+ RELEASE(self->adaptorName);
+ RELEASE(self->adaptorClassName);
+ RELEASE(self->connectionDictionary);
+ RELEASE(self->pkeyGeneratorDictionary);
+ RELEASE(self->userDictionary);
+ [super dealloc];
+}
+
+- (id)initWithContentsOfFile:(NSString*)filename
+{
+ NSDictionary *propList;
+
+ propList = [[[NSDictionary alloc]
+ initWithContentsOfFile:filename] autorelease];
+ if (propList == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"EOModel: Couldn't load model file: %@", filename];
+ }
+
+ if ((self = [self initWithPropertyList:propList])) {
+ self->path = [filename copy];
+ self->name = [[[filename lastPathComponent] stringByDeletingPathExtension]
+ copy];
+ }
+ return self;
+}
+
+- (id)initWithPropertyList:(NSDictionary *)propertyList {
+ if ((self = [self init])) {
+ int i, count;
+ NSArray *propListEntities;
+
+ if (propertyList == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"EOModel: Argument of initWithPropertyList: must "
+ @"not be the nil object"];
+ }
+ if (![propertyList isKindOfClass:[NSDictionary class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"EOModel: Argument of initWithPropertyList: must "
+ @"be kind of NSDictionary class"];
+ }
+
+ self->adaptorName =
+ [[propertyList objectForKey:@"adaptorName"] copy];
+ self->adaptorClassName =
+ [[propertyList objectForKey:@"adaptorClassName"] copy];
+ self->connectionDictionary =
+ [[propertyList objectForKey:@"connectionDictionary"] copy];
+ self->pkeyGeneratorDictionary =
+ [[propertyList objectForKey:@"pkeyGeneratorDictionary"] copy];
+ self->userDictionary =
+ [[propertyList objectForKey:@"userDictionary"] copy];
+
+ propListEntities = [propertyList objectForKey:@"entities"];
+
+ flags.errors = NO;
+ [self setCreateMutableObjects:YES];
+ count = [propListEntities count];
+ for (i = 0; i < count; i++) {
+ EOEntity *entity;
+
+ entity = [EOEntity entityFromPropertyList:
+ [propListEntities objectAtIndex:i]
+ model:self];
+ [self addEntity:entity];
+ }
+
+ count = [self->entities count];
+ for (i = 0; i < count; i++)
+ [[self->entities objectAtIndex:i] replaceStringsWithObjects];
+
+ /* Init relationships */
+ for (i = 0; i < count; i++) {
+ EOEntity *entity;
+ NSArray *rels;
+
+ entity = [self->entities objectAtIndex:i];
+ rels = [entity relationships];
+ /* Replace all the strings in relationships. */
+ [rels makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
+ }
+
+ /* Another pass to allow properly initialization of flattened
+ relationships. */
+ for (i = 0; i < count; i++) {
+ EOEntity* entity =
+ [self->entities objectAtIndex:i];
+ NSArray* rels = [entity relationships];
+
+ [rels makeObjectsPerformSelector:@selector(initFlattenedRelationship)];
+ }
+
+ /* Init attributes */
+ for (i = 0; i < count; i++) {
+ EOEntity *entity = [self->entities objectAtIndex:i];
+ NSArray *attrs = [entity attributes];
+
+ [attrs makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
+ }
+
+ [self setCreateMutableObjects:NO];
+ }
+ return flags.errors ? (void)AUTORELEASE(self), (id)nil : self;
+}
+
+- (id)initWithName:(NSString*)_name {
+ if ((self = [self init])) {
+ ASSIGN(self->name, _name);
+ }
+ return self;
+}
+
+/* class-description notifications */
+
+- (void)_requireClassDescriptionForEntityName:(NSNotification *)_notification {
+ NSString *entityName;
+
+ if ((entityName = [_notification object])) {
+ EOEntity *entity;
+
+ if ((entity = [self->entitiesByName objectForKey:entityName])) {
+ EOClassDescription *d;
+
+ d = [[EOEntityClassDescription alloc] initWithEntity:entity];
+ [EOClassDescription registerClassDescription:d
+ forClass:NSClassFromString([entity className])];
+ RELEASE(d); d = nil;
+ }
+ }
+}
+- (void)_requireClassDescriptionForClass:(NSNotification *)_notification {
+ Class clazz;
+ NSString *className;
+ EOEntity *entity;
+ EOClassDescription *d;
+
+ if ((clazz = [_notification object]) == nil)
+ return;
+ if ((className = NSStringFromClass(clazz)) == nil)
+ return;
+ if ((entity = [self->entitiesByClassName objectForKey:className]) == nil)
+ return;
+
+ d = [[EOEntityClassDescription alloc] initWithEntity:entity];
+ [EOClassDescription registerClassDescription:d forClass:clazz];
+ [d release]; d = nil;
+}
+
+/* property list */
+
+- (id)modelAsPropertyList {
+ NSMutableDictionary *model = [NSMutableDictionary dictionaryWithCapacity:64];
+ int i, count;
+
+ [model setObject:[[NSNumber numberWithInt:[isa version]] stringValue]
+ forKey:@"EOModelVersion"];
+ if (name)
+ [model setObject:name forKey:@"name"];
+ if (adaptorName)
+ [model setObject:adaptorName forKey:@"adaptorName"];
+ if (adaptorClassName)
+ [model setObject:adaptorClassName forKey:@"adaptorClassName"];
+ if (connectionDictionary)
+ [model setObject:connectionDictionary forKey:@"connectionDictionary"];
+ if (pkeyGeneratorDictionary) {
+ [model setObject:pkeyGeneratorDictionary
+ forKey:@"pkeyGeneratorDictionary"];
+ }
+ if (userDictionary)
+ [model setObject:userDictionary forKey:@"userDictionary"];
+ if (self->entities && (count = [self->entities count])) {
+ id entitiesArray = [NSMutableArray arrayWithCapacity:count];
+
+ [model setObject:entitiesArray forKey:@"entities"];
+ for (i = 0; i < count; i++) {
+ [entitiesArray addObject:
+ [[entities objectAtIndex:i] propertyList]];
+ }
+ }
+
+ return model;
+}
+
+- (BOOL)addEntity:(EOEntity *)entity {
+ NSString * entityName = [entity name];
+
+ if ([self->entitiesByName objectForKey:entityName])
+ return NO;
+
+ if ([self createsMutableObjects])
+ [(NSMutableArray*)self->entities addObject:entity];
+ else {
+ self->entities =
+ [[[self->entities autorelease] mutableCopy] autorelease];
+ [(NSMutableArray *)self->entities addObject:entity];
+ self->entities = [self->entities copy];
+ }
+
+ [self->entitiesByName setObject:entity forKey:entityName];
+ [self->entitiesByClassName setObject:entity forKey:[entity className]];
+ [entity setModel:self];
+ return YES;
+}
+
+- (void)removeEntityNamed:(NSString*)entityName {
+ id entity;
+
+ if (entityName == nil)
+ return;
+
+ entity = [self->entitiesByName objectForKey:entityName];
+
+ if ([self createsMutableObjects])
+ [(NSMutableArray*)self->entities removeObject:entity];
+ else {
+ self->entities = [AUTORELEASE(self->entities) mutableCopy];
+ [(NSMutableArray*)self->entities removeObject:entity];
+ self->entities = [AUTORELEASE(self->entities) copy];
+ }
+ [self->entitiesByName removeObjectForKey:entityName];
+ [entity resetModel];
+}
+
+- (EOEntity *)entityNamed:(NSString *)entityName {
+ return [self->entitiesByName objectForKey:entityName];
+}
+
+- (NSArray *)referencesToProperty:property {
+ [self notImplemented:_cmd];
+ return 0;
+}
+
+- (EOEntity *)entityForObject:object {
+ NSString *className;
+
+ className = NSStringFromClass([object class]);
+ return [self->entitiesByClassName objectForKey:className];
+}
+
+- (BOOL)incorporateModel:(EOModel*)model {
+ [self notImplemented:_cmd];
+ return 0;
+}
+
+- (void)setAdaptorName:(NSString*)_adaptorName {
+ id tmp = self->adaptorName;
+ self->adaptorName = [_adaptorName copyWithZone:[self zone]];
+ RELEASE(tmp); tmp = nil;
+}
+- (NSString *)adaptorName {
+ return self->adaptorName;
+}
+
+- (void)setAdaptorClassName:(NSString*)_adaptorClassName {
+ id tmp = self->adaptorClassName;
+ self->adaptorClassName = [_adaptorClassName copyWithZone:[self zone]];
+ RELEASE(tmp); tmp = nil;
+}
+- (NSString *)adaptorClassName {
+ return self->adaptorClassName;
+}
+
+- (void)setConnectionDictionary:(NSDictionary*)_connectionDictionary {
+ ASSIGN(self->connectionDictionary, _connectionDictionary);
+}
+- (NSDictionary *)connectionDictionary {
+ return self->connectionDictionary;
+}
+
+- (void)setPkeyGeneratorDictionary:(NSDictionary *)_dict {
+ ASSIGN(self->pkeyGeneratorDictionary, _dict);
+}
+- (NSDictionary *)pkeyGeneratorDictionary {
+ return self->pkeyGeneratorDictionary;
+}
+
+- (void)setUserDictionary:(NSDictionary *)_userDictionary {
+ ASSIGN(self->userDictionary, _userDictionary);
+}
+- (NSDictionary *)userDictionary {
+ return self->userDictionary;
+}
+
+- (NSString *)path {
+ return self->path;
+}
+- (NSString *)name {
+ return self->name;
+}
+- (NSArray *)entities {
+ NSMutableArray *ents;
+ int cnt, i;
+
+ cnt = [self->entities count];
+ ents = [NSMutableArray arrayWithCapacity:cnt];
+ for (i = 0; i < cnt; i++)
+ [ents addObject:[self->entities objectAtIndex:i]];
+
+ return ents;
+}
+
++ (int)version {
+ return 1;
+}
+
+/* description */
+
+- (NSString *)description {
+ NSMutableString *ms;
+ NSString *s;
+
+ ms = [NSMutableString stringWithCapacity:256];
+ [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+
+ if ((s = [self name])) [ms appendFormat:@" name=%@", s];
+ if ((s = [self path])) [ms appendFormat:@" path=%@", s];
+ if ((s = [self adaptorName])) [ms appendFormat:@" adaptor=%@", s];
+ if ((s = [self adaptorClassName])) [ms appendFormat:@" adaptor-class=%@", s];
+
+ [ms appendFormat:@" #entities=%d", [self->entities count]];
+
+ [ms appendString:@">"];
+ return ms;
+}
+
+@end /* EOModel */
+
+
+@implementation EOModel (EOModelPrivate)
+
+- (void)setCreateMutableObjects:(BOOL)flag {
+ if(flags.createsMutableObjects == flag)
+ return;
+
+ flags.createsMutableObjects = flag;
+
+ if(flags.createsMutableObjects)
+ self->entities = [AUTORELEASE(self->entities) mutableCopy];
+ else
+ self->entities = [AUTORELEASE(self->entities) copy];
+}
+
+- (BOOL)createsMutableObjects {
+ return flags.createsMutableObjects;
+}
+- (void)errorInReading {
+ flags.errors = YES;
+}
+
+@end /* EOModel (EOModelPrivate) */
+
+@implementation EOModel(NewInEOF2)
+
+- (void)loadAllModelObjects {
+}
+
+@end
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOModelGroup.m 1 2004-08-20 10:38:46Z znek $
+
+#include "EOModelGroup.h"
+#include "EOModel.h"
+#include "EOEntity.h"
+#import <EOControl/EOClassDescription.h>
+#include "common.h"
+
+@implementation EOModelGroup
+
+static EOModelGroup *defaultGroup = nil;
+static id<EOModelGroupClassDelegation> classDelegate = nil;
+
++ (void)setDefaultGroup:(EOModelGroup *)_group {
+ ASSIGN(defaultGroup, _group);
+}
+
++ (EOModelGroup *)defaultGroup {
+ EOModelGroup *group;
+
+ group = defaultGroup;
+
+ if (group == nil)
+ group = [[self classDelegate] defaultModelGroup];
+
+ if (group == nil)
+ group = [self globalModelGroup];
+
+ return group;
+}
+
++ (EOModelGroup *)globalModelGroup {
+ static EOModelGroup *globalModelGroup = nil;
+ NSEnumerator *bundles;
+ NSBundle *bundle;
+
+ if (globalModelGroup)
+ return globalModelGroup;
+
+ globalModelGroup = [[EOModelGroup alloc] init];
+
+ bundles = [[NSBundle allBundles] objectEnumerator];
+ while ((bundle = [bundles nextObject])) {
+ NSEnumerator *paths;
+ NSString *path;
+
+ paths = [[bundle pathsForResourcesOfType:@"eomodel" inDirectory:nil]
+ objectEnumerator];
+
+ while ((path = [paths nextObject])) {
+ EOModel *model;
+
+ model = [[EOModel alloc] initWithContentsOfFile:path];
+ if (model == nil) {
+ NSLog(@"WARNING: couldn't load model %@", path);
+ }
+ else {
+ [globalModelGroup addModel:model];
+ RELEASE(model);
+ }
+ }
+ }
+ return globalModelGroup;
+}
+
++ (void)setClassDelegate:(id<EOModelGroupClassDelegation>)_delegate {
+ ASSIGN(classDelegate, _delegate);
+}
++ (id<EOModelGroupClassDelegation>)classDelegate {
+ return classDelegate;
+}
+
+- (id)init {
+ self->nameToModel = [[NSMutableDictionary allocWithZone:[self zone]] init];
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->nameToModel);
+ [super dealloc];
+}
+
+/* instance delegate */
+
+- (void)setDelegate:(id<EOModelGroupDelegation>)_delegate {
+ self->delegate = _delegate;
+}
+- (id<EOModelGroupDelegation>)delegate {
+ return self->delegate;
+}
+
+/* accessors */
+
+- (void)addModel:(EOModel *)_model {
+ NSString *name;
+
+ name = [_model name];
+ if (name == nil) name = [[_model path] lastPathComponent];
+
+ if ([self->nameToModel objectForKey:name]) {
+ [NSException raise:@"NSInvalidArgumentException"
+ format:@"model group %@ already contains model named %@",
+ self, name];
+ }
+
+ [self->nameToModel setObject:_model forKey:name];
+
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:@"EOModelAddedNotification"
+ object:_model];
+}
+
+- (void)removeModel:(EOModel *)_model {
+ NSArray *allNames;
+
+ allNames = [self->nameToModel allKeysForObject:_model];
+ [self->nameToModel removeObjectsForKeys:allNames];
+
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:@"EOModelInvalidatedNotification"
+ object:_model];
+}
+
+- (EOModel *)addModelWithFile:(NSString *)_path {
+ EOModel *model;
+
+ model = [[EOModel alloc] initWithContentsOfFile:_path];
+ if (model == nil)
+ return nil;
+ AUTORELEASE(model);
+
+ [self addModel:model];
+
+ return model;
+}
+
+- (EOModel *)modelNamed:(NSString *)_name {
+ return [self->nameToModel objectForKey:_name];
+}
+- (EOModel *)modelWithPath:(NSString *)_path {
+ NSEnumerator *e;
+ EOModel *m;
+ NSString *p;
+
+ p = [_path stringByStandardizingPath];
+ if (p == nil) p = _path;
+
+ e = [self->nameToModel objectEnumerator];
+ while ((m = [e nextObject])) {
+ NSString *mp;
+
+ mp = [[m path] stringByStandardizingPath];
+ if (mp == nil) mp = [m path];
+
+ if ([p isEqual:mp])
+ return m;
+ }
+ return m;
+}
+
+- (NSArray *)modelNames {
+ return [self->nameToModel allKeys];
+}
+- (NSArray *)models {
+ return [self->nameToModel allValues];
+}
+
+- (void)loadAllModelObjects {
+ [[self->nameToModel allValues] makeObjectsPerformSelector:_cmd];
+}
+
+/* entities */
+
+- (EOEntity *)entityForObject:(id)_object {
+ NSEnumerator *e;
+ EOModel *m;
+
+ e = [self->nameToModel objectEnumerator];
+ while ((m = [e nextObject])) {
+ EOEntity *entity;
+
+ if ((entity = [m entityForObject:_object]))
+ return entity;
+ }
+ return nil;
+}
+
+- (EOEntity *)entityNamed:(NSString *)_name {
+ NSEnumerator *e;
+ EOModel *m;
+
+ e = [self->nameToModel objectEnumerator];
+ while ((m = [e nextObject])) {
+ EOEntity *entity;
+
+ if ((entity = [m entityNamed:_name]))
+ return entity;
+ }
+ return nil;
+}
+
+- (EOFetchSpecification *)fetchSpecificationNamed:(NSString *)_name
+ entityNamed:(NSString *)_entityName
+{
+ return [[self entityNamed:_entityName] fetchSpecificationNamed:_name];
+}
+
+/* description */
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@[0x%08X]: models=%@>",
+ NSStringFromClass([self class]),
+ self,
+ [[self modelNames] componentsJoinedByString:@","]];
+}
+
+@end /* EOModelGroup */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EONotQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $
+
+#import "EOSQLQualifier.h"
+#include "common.h"
+
+@implementation EONotQualifier(SQLQualifier)
+
+/* SQL qualifier generation */
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity {
+ EOSQLQualifier *q;
+
+ q = [self->qualifier sqlQualifierForEntity:_entity];
+ [q negate];
+ return q;
+}
+
+@end /* EONotQualifier */
--- /dev/null
+/*
+ EOObjectUniquer.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOEntity.h"
+#import "EOObjectUniquer.h"
+#import "EOPrimaryKeyDictionary.h"
+#import "EODatabaseFault.h"
+#import "EOGenericRecord.h"
+
+static unsigned uniquerHash(NSMapTable* table, EOUniquerRecord* rec) {
+ // efficient hash for dictionaries is done in the concrete
+ // dictionaries implementation; dictionaries are allocated
+ // from EOPrimaryKeyDictionary concrete subclasses
+ return ((unsigned)(rec->entity) >> 4) +
+ ((EOPrimaryKeyDictionary*)(rec->pkey))->fastHash;
+}
+
+static BOOL uniquerCompare(NSMapTable *table, EOUniquerRecord *rec1,
+ EOUniquerRecord *rec2) {
+ // efficient compare between dictionaries is done in the concrete
+ // dictionaries implementation; dictionaries are allocated
+ // from EOPrimaryKeyDictionary concrete subclasses
+ return (rec1->entity == rec2->entity) && [rec1->pkey fastIsEqual:rec2->pkey];
+}
+
+static NSString* uniqDescription(NSMapTable *t, EOUniquerRecord* rec) {
+ return [NSString stringWithFormat:
+ @"<<pkey:%08x entity:%08x object:%08x snapshot:%08x>>",
+ rec->pkey, rec->entity, rec->object, rec->snapshot];
+}
+
+static void uniquerRetain(NSMapTable *table, EOUniquerRecord* rec) {
+ rec->refCount++;
+}
+
+static void uniquerRelease(NSMapTable *table, EOUniquerRecord *rec) {
+ rec->refCount--;
+
+ if (rec->refCount <= 0) {
+ RELEASE(rec->pkey); rec->pkey = NULL;
+ RELEASE(rec->entity); rec->entity = NULL;
+ RELEASE(rec->snapshot); rec->snapshot = NULL;
+ Free(rec); rec = NULL;
+ }
+}
+
+static inline EOUniquerRecord *uniquerCreate(id pkey, id entity, id object,
+ id snapshot) {
+ EOUniquerRecord *rec = NULL;
+
+ rec = (EOUniquerRecord *)Malloc(sizeof(EOUniquerRecord));
+ rec->refCount = 0;
+ rec->pkey = RETAIN(pkey);
+ rec->entity = RETAIN(entity);
+ rec->object = object;
+ rec->snapshot = RETAIN(snapshot);
+
+ return rec;
+}
+
+static void uniquerNoAction(NSMapTable * t, const void *_object) {
+}
+
+static NSMapTableKeyCallBacks uniquerKeyMapCallbacks = {
+ (unsigned(*)(NSMapTable *, const void *))uniquerHash,
+ (BOOL(*)(NSMapTable *, const void *, const void *))uniquerCompare,
+ (void (*)(NSMapTable *, const void *))uniquerNoAction,
+ (void (*)(NSMapTable *, void *))uniquerNoAction,
+ (NSString *(*)(NSMapTable *, const void *))uniqDescription,
+ (const void *)NULL
+};
+
+static NSMapTableValueCallBacks uniquerValueMapCallbacks = {
+ (void (*)(NSMapTable *, const void *))uniquerRetain,
+ (void (*)(NSMapTable *, void *))uniquerRelease,
+ (NSString *(*)(NSMapTable *, const void *))uniqDescription
+};
+
+static int initialHashSize = 1021;
+
+@implementation EOObjectUniquer
+
+static NSMutableArray *uniquerExtent = nil;
+static NSRecursiveLock *lock = nil;
+
++ (void)initialize {
+ static BOOL isInitialized = NO;
+ if (!isInitialized) {
+ isInitialized = YES;
+
+ uniquerExtent = [[NSMutableArray alloc] initWithCapacity:16];
+ // THREAD: lock = [[NSRecursiveLock alloc] init];
+ }
+}
+
+static inline void _addUniquerInstance(EOObjectUniquer *_uniquer) {
+ [lock lock];
+ [uniquerExtent addObject:[NSValue valueWithNonretainedObject:_uniquer]];
+ [lock unlock];
+}
+static inline void _removeUniquerInstance(EOObjectUniquer *_uniquer) {
+ [lock lock];
+ {
+ int i;
+
+ for (i = [uniquerExtent count] - 1; i >= 0; i--) {
+ EOObjectUniquer *uniquer;
+
+ uniquer = [[uniquerExtent objectAtIndex:i] nonretainedObjectValue];
+ if (uniquer == _uniquer) {
+ [uniquerExtent removeObjectAtIndex:i];
+ break;
+ }
+ }
+ }
+ [lock unlock];
+}
+
+// Initializing a uniquing dictionary
+
+- (id)init {
+ self->primaryKeyToRec = NSCreateMapTable(uniquerKeyMapCallbacks,
+ uniquerValueMapCallbacks,
+ initialHashSize);
+#if LIB_FOUNDATION_LIBRARY
+ self->objectsToRec = NSCreateMapTableInvisibleKeysOrValues
+ (NSNonOwnedPointerMapKeyCallBacks,
+ uniquerValueMapCallbacks, initialHashSize,
+ YES, NO);
+#else
+ self->objectsToRec = NSCreateMapTable
+ (NSNonOwnedPointerMapKeyCallBacks,
+ uniquerValueMapCallbacks, initialHashSize);
+#endif
+ self->keyRecord = uniquerCreate(nil, nil, nil, nil);
+
+ _addUniquerInstance(self);
+
+ return self;
+}
+
+- (void)dealloc {
+ [self forgetAllObjects];
+ _removeUniquerInstance(self);
+
+ NSFreeMapTable(self->objectsToRec);
+ NSFreeMapTable(self->primaryKeyToRec);
+ if (self->keyRecord) {
+ Free(self->keyRecord);
+ self->keyRecord = NULL;
+ }
+ [super dealloc];
+}
+
+// Transfer self to parent
+
+- (void)transferTo:(EOObjectUniquer *)_dest
+ objects:(BOOL)isKey andSnapshots:(BOOL)isSnap
+{
+ EOUniquerRecord *key = NULL;
+ EOUniquerRecord *rec = NULL;
+ NSMapEnumerator enumerator = NSEnumerateMapTable(primaryKeyToRec);
+
+ while(NSNextMapEnumeratorPair(&enumerator, (void**)(&key), (void**)(&rec))) {
+ [_dest recordObject:rec->object
+ primaryKey: isKey ? rec->pkey : nil
+ entity: isKey ? rec->entity : nil
+ snapshot: isSnap ? rec->snapshot : nil];
+ }
+ [self forgetAllObjects];
+}
+
+// Handling objects
+
+- (void)forgetObject:(id)_object {
+ EOUniquerRecord *rec = NULL;
+
+ if (_object == nil)
+ return;
+
+ rec = (EOUniquerRecord *)NSMapGet(self->objectsToRec, _object);
+
+ if (rec == NULL)
+ return;
+
+ /*
+ NSLog(@"Uniquer[0x%08X]: forget object 0x%08X<%s> entity=%@",
+ self, _object, class_get_class_name(*(Class *)_object),
+ [[_object entity] name]);
+ */
+
+ if (rec->pkey)
+ NSMapRemove(self->primaryKeyToRec, rec);
+ NSMapRemove(self->objectsToRec, _object);
+}
+
+- (void)forgetAllObjects {
+ NSResetMapTable(self->primaryKeyToRec);
+ NSResetMapTable(self->objectsToRec);
+}
+
+- (void)forgetAllSnapshots {
+ NSMapEnumerator enumerator;
+ EOUniquerRecord *rec = NULL;
+ id key = nil;
+
+ NSLog(@"uniquer 0x%08X forgetAllSnapshots ..", self);
+
+ enumerator = NSEnumerateMapTable(self->objectsToRec);
+ while (NSNextMapEnumeratorPair(&enumerator, (void**)(&key), (void**)(&rec))) {
+ RELEASE(rec->snapshot);
+ rec->snapshot = nil;
+ }
+}
+
+- (id)objectForPrimaryKey:(NSDictionary *)_key entity:(EOEntity *)_entity {
+ EOUniquerRecord *rec;
+
+ if (_key == nil || _entity == nil)
+ return nil;
+
+ if (![_key isKindOfClass:[EOPrimaryKeyDictionary class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"attempt to record object with non "
+ @" EOPrimaryKeyDictionary class in EOObjectUniquer."
+ @"This is a bug in EODatabase/Context/Channel."];
+ }
+
+ keyRecord->pkey = _key;
+ keyRecord->entity = _entity;
+
+ rec = (EOUniquerRecord*)NSMapGet(primaryKeyToRec, keyRecord);
+
+ return rec ? rec->object : nil;
+}
+
+- (EOUniquerRecord *)recordForObject:(id)_object {
+ return (_object == nil)
+ ? (EOUniquerRecord *)NULL
+ : (EOUniquerRecord *)NSMapGet(self->objectsToRec, _object);
+}
+
+- (void)recordObject:(id)_object
+ primaryKey:(NSDictionary *)_key
+ entity:(EOEntity *)_entity
+ snapshot:(NSDictionary *)_snapshot
+{
+ EOUniquerRecord *rec = NULL;
+ EOUniquerRecord *orc = NULL;
+
+ if (_object == nil)
+ return;
+
+ if ((_key == nil) || (_entity == nil)) {
+ _key = nil;
+ _entity = nil;
+ }
+
+ if ((_key == nil) && (_snapshot == nil))
+ return;
+
+ if (_key && ![_key isKindOfClass:[EOPrimaryKeyDictionary class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"attempt to record object with non "
+ @" EOPrimaryKeyDictionary class in EOObjectUniquer."
+ @"This is a bug in EODatabase/Context/Channel."];
+ }
+
+ keyRecord->pkey = _key;
+ keyRecord->entity = _entity;
+
+ rec = (EOUniquerRecord*)NSMapGet(objectsToRec, _object);
+ if (rec) {
+ if (_key && uniquerCompare(NULL, rec, keyRecord)) {
+ ASSIGN(rec->snapshot, _snapshot);
+ return;
+ }
+ if (_key) {
+ orc = (EOUniquerRecord*)NSMapGet(primaryKeyToRec, keyRecord);
+ if (orc && orc != rec) {
+ if (orc->pkey)
+ NSMapRemove(primaryKeyToRec, orc);
+
+ NSMapRemove(objectsToRec, orc->object);
+ }
+ NSMapRemove(primaryKeyToRec, rec);
+ }
+ ASSIGN(rec->pkey, _key);
+ ASSIGN(rec->entity, _entity);
+ ASSIGN(rec->snapshot, _snapshot);
+
+ if (_key)
+ NSMapInsertKnownAbsent(primaryKeyToRec, rec, rec);
+ return;
+ }
+
+ if (_key)
+ rec = (EOUniquerRecord*)NSMapGet(primaryKeyToRec, keyRecord);
+ if (rec) {
+ if (rec->object == _object) {
+ ASSIGN(rec->snapshot, _snapshot);
+ return;
+ }
+
+ NSMapRemove(objectsToRec, rec->object);
+
+ ASSIGN(rec->snapshot, _snapshot);
+ rec->object = _object;
+ NSMapInsertKnownAbsent(objectsToRec, _object, rec);
+ return;
+ }
+
+ rec = uniquerCreate(_key, _entity, _object, _snapshot);
+ if (_key)
+ NSMapInsertKnownAbsent(primaryKeyToRec, rec, rec);
+ NSMapInsertKnownAbsent(objectsToRec, _object, rec);
+}
+
+
+/* This method is called by the Boehm's garbage collector when an object
+ is finalized */
+- (void)_objectWillFinalize:(id)_object {
+ // printf ("_objectWillFinalize: %p (%s)\n",
+ // _object, class_get_class_name ([_object class]));
+ [self forgetObject:_object];
+}
+
++ (void)forgetObject:(id)_object {
+ [lock lock];
+ {
+ int i;
+
+ for (i = [uniquerExtent count] - 1; i >= 0; i--) {
+ EOObjectUniquer *uniquer;
+
+ uniquer = [[uniquerExtent objectAtIndex:i] nonretainedObjectValue];
+ [uniquer forgetObject:_object];
+ }
+ }
+ [lock unlock];
+}
+
+@end /* EOObjectUniquer */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOOrQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $
+
+#import "EOSQLQualifier.h"
+#include "common.h"
+
+@implementation EOOrQualifier(SQLQualifier)
+
+/* SQL qualifier generation */
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity {
+ unsigned cc = [self->qualifiers count];
+
+ if (cc == 0)
+ return nil;
+ else if (cc == 1)
+ return [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity];
+ else if (cc == 2) {
+ id left;
+ id right;
+
+ left = [[self->qualifiers objectAtIndex:0] sqlQualifierForEntity:_entity];
+ right = [[self->qualifiers objectAtIndex:1] sqlQualifierForEntity:_entity];
+ [left disjoinWithQualifier:right];
+ return left;
+ }
+ else {
+ EOSQLQualifier *masterQ;
+ unsigned i;
+
+ for (i = 0, masterQ = nil; i < cc; i++) {
+ EOSQLQualifier *q;
+
+ q = [[self->qualifiers objectAtIndex:i]
+ sqlQualifierForEntity:_entity];
+ if (masterQ == nil)
+ masterQ = q;
+ else
+ [masterQ disjoinWithQualifier:q];
+ }
+ return masterQ;
+ }
+}
+
+@end /* EOOrQualifier */
--- /dev/null
+/*
+ EOPrimaryKeyDictionary.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOPrimaryKeyDictionary.h"
+#import <EOControl/EONull.h>
+
+/*
+ * Concrete Classes declaration
+ */
+
+@interface EOSinglePrimaryKeyDictionary : EOPrimaryKeyDictionary
+{
+ id key;
+ id value;
+}
+- (id)initWithObject:(id)anObject forKey:(id)aKey;
+- (id)key;
+@end
+
+@interface EOSinglePrimaryKeyDictionaryEnumerator : NSEnumerator
+{
+ id key;
+}
+
+- (id)iniWithObject:(id)_key;
+
+@end
+
+@interface EOMultiplePrimaryKeyDictionary : EOPrimaryKeyDictionary
+{
+ int count;
+ NSArray *keys;
+ id values[0];
+}
+
++ (id)allocWithZone:(NSZone *)_zone capacity:(int)_capacity;
+- (id)initWithKeys:(NSArray *)_keys fromDictionary:(NSDictionary *)_dict;
+
+@end
+
+/*
+ * Single key dictionary
+ */
+
+@implementation EOSinglePrimaryKeyDictionary
+
+- (id)initWithObject:(id)_object forKey:(id)_key {
+ NSAssert(_key, @"provided invalid key (is nil)");
+ NSAssert1(_object, @"provided invalid value (is nil), key=%@", _key);
+
+ if ([_object isKindOfClass:[EONull class]]) {
+ NSLog(@"value of primary key %@ is null ..", _key);
+ RELEASE(self);
+ return nil;
+ }
+
+ NSAssert(![_object isKindOfClass:[EONull class]],
+ @"value of primary key may not be null !");
+
+ self->key = RETAIN(_key);
+ self->value = RETAIN(_object);
+ self->fastHash = [_object hash];
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->key);
+ RELEASE(self->value);
+ [super dealloc];
+}
+
+/* operations */
+
+- (NSEnumerator *)keyEnumerator {
+ return AUTORELEASE([[EOSinglePrimaryKeyDictionaryEnumerator alloc]
+ iniWithObject:self->key]);
+}
+
+- (id)objectForKey:(id)_key {
+ return [key isEqual:_key] ? value : nil;
+}
+
+- (unsigned int)count {
+ return 1;
+}
+
+- (unsigned int)hash {
+ return 1;
+}
+
+- (id)key {
+ return self->key;
+}
+
+- (NSArray *)allKeys {
+ return [NSArray arrayWithObject:key];
+}
+
+- (NSArray *)allValues {
+ return [NSArray arrayWithObject:value];
+}
+
+- (BOOL)isEqualToDictionary:(NSDictionary *)other {
+ if (self == (EOSinglePrimaryKeyDictionary*)other)
+ return YES;
+ if (self->isa == ((EOSinglePrimaryKeyDictionary*)other)->isa) {
+ if (fastHash == ((EOSinglePrimaryKeyDictionary*)other)->fastHash &&
+ [key isEqual:((EOSinglePrimaryKeyDictionary*)other)->key] &&
+ [value isEqual:((EOSinglePrimaryKeyDictionary*)other)->value])
+ return YES;
+ else
+ return NO;
+ }
+ if ([other count] != 1)
+ return NO;
+ return [value isEqual:[other objectForKey:key]];
+}
+
+- (id)copyWithZone:(NSZone*)zone {
+ if ([self zone] == (zone ? zone : NSDefaultMallocZone()))
+ return RETAIN(self);
+ else
+ return [[[self class] allocWithZone:zone]
+ initWithObject:value forKey:key];
+}
+- (id)copy {
+ return [self copyWithZone:NULL];
+}
+
+- (BOOL)fastIsEqual:(id)other {
+ if (self == other)
+ return YES;
+ if (self->isa == ((EOSinglePrimaryKeyDictionary*)other)->isa) {
+ if (fastHash == ((EOSinglePrimaryKeyDictionary*)other)->fastHash &&
+ key == ((EOSinglePrimaryKeyDictionary*)other)->key &&
+ [value isEqual:((EOSinglePrimaryKeyDictionary*)other)->value])
+ return YES;
+ else
+ return NO;
+ }
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"fastIsEqual: compares only "
+ @"EOPrimaryKeyDictionary instances !"];
+ return NO;
+}
+
+@end /* EOSinglePrimaryKeyDictionary */
+
+@implementation EOSinglePrimaryKeyDictionaryEnumerator
+
+- (id)iniWithObject:(id)aKey {
+ self->key = RETAIN(aKey);
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->key);
+ [super dealloc];
+}
+
+/* operations */
+
+- (id)nextObject {
+ id tmp = self->key;
+ self->key = nil;
+ return AUTORELEASE(tmp);
+}
+
+@end /* EOSinglePrimaryKeyDictionaryEnumerator */
+
+/*
+ * Multiple key dictionary is very time-memory efficient
+ */
+
+@implementation EOMultiplePrimaryKeyDictionary
+
++ (id)allocWithZone:(NSZone *)zone capacity:(int)capacity {
+ return NSAllocateObject(self, sizeof(id)*capacity, zone);
+}
+
+- (id)initWithKeys:(NSArray*)theKeys fromDictionary:(NSDictionary*)dict; {
+ int i;
+
+ self->count = [theKeys count];
+ self->keys = RETAIN(theKeys);
+ self->fastHash = 0;
+
+ for (i = 0; i < count; i++) {
+ self->values[i] = [dict objectForKey:[keys objectAtIndex:i]];
+ RETAIN(self->values[i]);
+
+ NSAssert(![values[i] isKindOfClass:[EONull class]],
+ @"primary key values may not be null !");
+
+ if (self->values[i] == nil) {
+ AUTORELEASE(self);
+ return nil;
+ }
+ self->fastHash += [self->values[i] hash];
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ int i;
+
+ for (i = 0; i < count; i++)
+ RELEASE(self->values[i]);
+ RELEASE(self->keys);
+ [super dealloc];
+}
+
+/* operations */
+
+- (NSEnumerator *)keyEnumerator {
+ return [self->keys objectEnumerator];
+}
+
+- (id)objectForKey:(id)aKey {
+ int max, min, mid;
+ // Binary search for key's index
+ for (min = 0, max = count-1; min <= max; ) {
+ NSComparisonResult ord;
+
+ mid = (min+max) >> 1;
+ ord = [(NSString*)aKey compare:(NSString*)[keys objectAtIndex:mid]];
+ if (ord == NSOrderedSame)
+ return values[mid];
+ if (ord == NSOrderedDescending)
+ min = mid+1;
+ else
+ max = mid-1;
+ }
+ return nil;
+}
+
+- (unsigned int)count {
+ return self->count;
+}
+
+- (unsigned int)hash {
+ return self->count;
+}
+
+- (NSArray *)allKeys {
+ return self->keys;
+}
+
+- (NSArray *)allValues {
+ return AUTORELEASE([[NSArray alloc] initWithObjects:values count:count]);
+}
+
+- (BOOL)isEqualToDictionary:(NSDictionary *)other {
+ int i;
+
+ if (self == (EOMultiplePrimaryKeyDictionary*)other)
+ return YES;
+ if ((unsigned)self->count != [other count])
+ return NO;
+ for (i = 0; i < self->count; i++) {
+ if (![values[i] isEqual:[other objectForKey:[keys objectAtIndex:i]]])
+ return NO;
+ }
+ return YES;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ if ([self zone] == (zone ? zone : NSDefaultMallocZone()))
+ return RETAIN(self);
+ else {
+ return [[[self class]
+ allocWithZone:zone capacity:count]
+ initWithKeys:keys fromDictionary:self];
+ }
+}
+- (id)copy {
+ return [self copyWithZone:NULL];
+}
+
+- (unsigned)fastHash {
+ return self->fastHash;
+}
+
+- (BOOL)fastIsEqual:(id)aDict {
+ int i;
+
+ if (self->isa != ((EOMultiplePrimaryKeyDictionary*)aDict)->isa) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"fastIsEqual: can compare only "
+ @"EOPrimaryKeyDictionary instances"];
+ }
+ if (self->count != ((EOMultiplePrimaryKeyDictionary*)aDict)->count ||
+ self->fastHash != ((EOMultiplePrimaryKeyDictionary*)aDict)->fastHash ||
+ self->keys != ((EOMultiplePrimaryKeyDictionary*)aDict)->keys)
+ return NO;
+
+ for (i = count - 1; i >= 0; i--) {
+ if (![values[i] isEqual:
+ ((EOMultiplePrimaryKeyDictionary*)aDict)->values[i]])
+ return NO;
+ }
+ return YES;
+}
+
+@end /* EOMultiplePrimaryKeyDictionary */
+
+/*
+ * Cluster Abstract class
+ */
+
+@implementation EOPrimaryKeyDictionary
+
++ (id)allocWithZone:(NSZone *)_zone {
+ return NSAllocateObject(self, 0, _zone);
+}
+
++ (id)dictionaryWithKeys:(NSArray *)keys fromDictionary:(NSDictionary *)dict {
+ if ([dict count] == 0)
+ return nil;
+
+ if ([keys count] == 1) {
+ id key = [keys objectAtIndex:0];
+ id keyValue = [dict objectForKey:key];
+
+ NSAssert2(keyValue, @"dictionary %@ contained no value for key %@ ..",
+ dict, key);
+
+ // Check if already an EOSinglePrimaryKeyDictionary from same entity
+ // return it since the new one will be identical to it; we have
+ // no problem regarding its correctness since it was built by this
+ // method !
+ if ([dict isKindOfClass:[EOSinglePrimaryKeyDictionary class]]) {
+ if ([(EOSinglePrimaryKeyDictionary*)dict key]==key)
+ return dict;
+ }
+
+ //HH:
+ // Check if the keyValue is EONull. If this is the case, return nil.
+ // Primary keys are always 'not null'.
+ if ([keyValue isKindOfClass:[EONull class]])
+ return nil;
+
+ // Alloc single key dictionary
+ return AUTORELEASE([[EOSinglePrimaryKeyDictionary alloc]
+ initWithObject:keyValue
+ forKey:key]);
+ }
+ else {
+ // Check if already an EOMultiplePrimaryKeyDictionary from same entity
+ // return it since the new one will be identical to it; we have
+ // no problem regarding its correctness since it was built by this
+ // method !
+ if ([dict isKindOfClass:[EOMultiplePrimaryKeyDictionary class]] &&
+ [dict allKeys] == keys)
+ return dict;
+ // Alloc multi-key dictionary
+ return AUTORELEASE([[EOMultiplePrimaryKeyDictionary
+ allocWithZone:NULL capacity:[keys count]]
+ initWithKeys:keys fromDictionary:dict]);
+ }
+}
+
++ (id)dictionaryWithObject:(id)object forKey:(id)key {
+ return AUTORELEASE([[EOSinglePrimaryKeyDictionary alloc]
+ initWithObject:object forKey:key]);
+}
+
+- (unsigned)fastHash {
+ return self->fastHash;
+}
+
+- (BOOL)fastIsEqual:aDict {
+ // TODO - request concrete implementation
+ return NO;
+}
+
+@end /* EOPrimaryKeyDictionary */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOQualifier+SQL.m 1 2004-08-20 10:38:46Z znek $
+
+#include "EOSQLExpression.h"
+#include "EOSQLQualifier.h"
+#include <EOControl/EOQualifier.h>
+#include "common.h"
+
+@implementation EOAndQualifier(SQLGeneration)
+
+- (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr {
+ return [_sqlExpr sqlStringForConjoinedQualifiers:[self qualifiers]];
+}
+
+- (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity {
+ NSArray *array;
+ id objects[self->count + 1];
+ unsigned i;
+
+ IMP objAtIdx;
+
+ objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)];
+
+ for (i = 0; i < self->count; i++) {
+ id q, newq;
+
+ q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i);
+ newq = [q schemaBasedQualifierWithRootEntity:_entity];
+ if (newq == nil) newq = q;
+
+ objects[i] = newq;
+ }
+
+ array = [NSArray arrayWithObjects:objects count:self->count];
+ return [[[[self class] alloc] initWithQualifierArray:array] autorelease];
+}
+
+@end /* EOAndQualifier(SQLGeneration) */
+
+@implementation EOOrQualifier(SQLGeneration)
+
+- (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr {
+ return [_sqlExpr sqlStringForDisjoinedQualifiers:[self qualifiers]];
+}
+
+- (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity {
+ NSArray *array;
+ id objects[self->count + 1];
+ unsigned i;
+
+ IMP objAtIdx;
+
+ objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)];
+
+ for (i = 0; i < self->count; i++) {
+ id q, newq;
+
+ q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i);
+ newq = [q schemaBasedQualifierWithRootEntity:_entity];
+ if (newq == nil) newq = q;
+
+ objects[i] = newq;
+ }
+
+ array = [NSArray arrayWithObjects:objects count:self->count];
+ return [[[[self class] alloc] initWithQualifierArray:array] autorelease];
+}
+
+@end /* EOOrQualifier(SQLGeneration) */
+
+@implementation EONotQualifier(SQLGeneration)
+
+- (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr {
+ return [_sqlExpr sqlStringForNegatedQualifier:[self qualifier]];
+}
+
+- (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity {
+ EOQualifier *sq;
+
+ sq = [(id<EOQualifierSQLGeneration>)self->qualifier
+ schemaBasedQualifierWithRootEntity:_entity];
+ if (sq == self->qualifier)
+ return self;
+
+ sq = [[EONotQualifier alloc] initWithQualifier:sq];
+ return [sq autorelease];
+}
+
+@end /* EONotQualifier(SQLGeneration) */
+
+@implementation EOKeyValueQualifier(SQLGeneration)
+
+- (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr {
+ return [_sqlExpr sqlStringForKeyValueQualifier:self];
+}
+
+- (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity {
+ NSLog(@"ERROR(%s): subclasses need to override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+@end /* EOKeyValueQualifier(SQLGeneration) */
+
+@implementation EOKeyComparisonQualifier(SQLGeneration)
+
+- (NSString *)sqlStringForSQLExpression:(EOSQLExpression *)_sqlExpr {
+ return [_sqlExpr sqlStringForKeyComparisonQualifier:self];
+}
+
+- (EOQualifier *)schemaBasedQualifierWithRootEntity:(EOEntity *)_entity {
+ NSLog(@"ERROR(%s): subclasses need to override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+@end /* EOKeyComparisonQualifier(SQLGeneration) */
--- /dev/null
+/*
+ EOQualifierScanner.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Helge Hess <helge.hess@mdlink.de>
+ Date: September 1996
+ November 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOQualifierScanner.m 1 2004-08-20 10:38:46Z znek $
+
+#import "common.h"
+#include "EOQualifierScanner.h"
+#include "EOFExceptions.h"
+#include "EOEntity.h"
+#include "EOSQLQualifier.h"
+#include <EOControl/EONull.h>
+
+#if LIB_FOUNDATION_LIBRARY
+# import <extensions/DefaultScannerHandler.h>
+# import <extensions/PrintfFormatScanner.h>
+#else
+# import "DefaultScannerHandler.h"
+# import "PrintfFormatScanner.h"
+#endif
+
+@implementation EOQualifierScannerHandler
+
+- (id)init {
+ [super init];
+
+ specHandler['d'] = [self methodForSelector:@selector(convertInt:scanner:)];
+ specHandler['f']
+ = [self methodForSelector:@selector(convertFloat:scanner:)];
+ specHandler['s']
+ = [self methodForSelector:@selector(convertCString:scanner:)];
+ specHandler['A']
+ = [self methodForSelector:@selector(convertProperty:scanner:)];
+ specHandler['@']
+ = [self methodForSelector:@selector(convertObject:scanner:)];
+ return self;
+}
+
+- (void)setEntity:(EOEntity *)_entity
+{
+ ASSIGN(self->entity, _entity);
+}
+
+- (void)dealloc {
+ RELEASE(self->entity);
+ [super dealloc];
+}
+
+/* conversions */
+
+- (NSString *)convertInt:(va_list *)pInt scanner:(FormatScanner*)scanner {
+ char buffer[256];
+ sprintf(buffer, [scanner currentSpecifier], va_arg(*pInt, int));
+ return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)convertFloat:(va_list *)pFloat scanner:(FormatScanner*)scanner {
+ char buffer[256];
+ sprintf(buffer, [scanner currentSpecifier], va_arg(*pFloat, double));
+ return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)convertCString:(va_list *)pString scanner:(FormatScanner*)scanner {
+ char *string;
+ string = va_arg(*pString, char*);
+ return string ? [NSString stringWithCString:string] : @"";
+}
+
+- (NSString*)convertProperty:(va_list*)pString scanner:(FormatScanner*)scanner {
+ NSString *propertyName;
+ id property;
+
+ propertyName = va_arg(*pString, id);
+ property = [entity propertyNamed:propertyName];
+
+ if(property == nil) {
+ [[[InvalidPropertyException alloc]
+ initWithName:propertyName entity:entity] raise];
+ }
+ return propertyName;
+}
+
+- (NSString *)convertObject:(va_list *)pId scanner:scanner {
+ id object = va_arg(*pId, id);
+ if (object == nil) object = [NSNull null];
+ return [object expressionValueForContext:nil];
+}
+
+@end /* EOQualifierScannerHandler */
+
+@implementation EOQualifierEnumScannerHandler
+
+- (id)init {
+ [super init];
+
+ specHandler['d'] = [self methodForSelector:@selector(convertInt:scanner:)];
+ specHandler['f']
+ = [self methodForSelector:@selector(convertFloat:scanner:)];
+ specHandler['s']
+ = [self methodForSelector:@selector(convertCString:scanner:)];
+ specHandler['A']
+ = [self methodForSelector:@selector(convertProperty:scanner:)];
+ specHandler['@']
+ = [self methodForSelector:@selector(convertObject:scanner:)];
+ return self;
+}
+
+- (void)setEntity:(EOEntity *)_entity {
+ ASSIGN(self->entity, _entity);
+}
+
+- (void)dealloc {
+ RELEASE(self->entity);
+ [super dealloc];
+}
+
+- (NSString *)convertInt:(NSEnumerator **)pInt scanner:(FormatScanner*)scanner {
+ char buffer[256];
+ sprintf(buffer, [scanner currentSpecifier], [[*pInt nextObject] intValue]);
+ return [NSString stringWithCString:buffer];
+}
+
+- (NSString *)convertFloat:(NSEnumerator **)pFloat
+ scanner:(FormatScanner *)scanner
+{
+ char buffer[256];
+ sprintf(buffer, [scanner currentSpecifier],
+ [[*pFloat nextObject] doubleValue]);
+ return [NSString stringWithCString:buffer];
+}
+
+- (NSString *)convertCString:(NSEnumerator **)pString
+ scanner:(FormatScanner *)scanner
+{
+ id str;
+
+ if ((str = [*pString nextObject]) == nil)
+ str = @"";
+ else if ([str isKindOfClass:[NSString class]])
+ ;
+ else if ([str respondsToSelector:@selector(stringValue)])
+ str = [str stringValue];
+ else
+ str = [str description];
+
+ return (str == nil) ? @"" : str;
+}
+
+- (NSString *)convertProperty:(NSEnumerator **)pString
+ scanner:(FormatScanner *)scanner
+{
+ NSString *propertyName;
+ id property;
+
+ propertyName = [*pString nextObject];
+ property = [entity propertyNamed:propertyName];
+
+ if(property == nil) {
+ [[[InvalidPropertyException alloc]
+ initWithName:propertyName entity:entity] raise];
+ }
+ return propertyName;
+}
+
+- (NSString *)convertObject:(NSEnumerator **)pId scanner:(id)scanner {
+ id object;
+ object = [*pId nextObject];
+ return [object expressionValueForContext:nil];
+}
+
+@end /* EOQualifierEnumScannerHandler */
--- /dev/null
+/*
+ EOQuotedExpression.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import <Foundation/NSString.h>
+#import <Foundation/NSArray.h>
+#import "common.h"
+#import "EOQuotedExpression.h"
+
+@implementation EOQuotedExpression
+
+- (id)expressionValueForContext:(id<EOExpressionContext>)_context {
+ NSMutableString *result;
+ NSArray *components;
+ id expr;
+
+ expr = [self->expression expressionValueForContext:_context];
+ components = [expr componentsSeparatedByString:quote];
+ result = [[NSMutableString alloc] initWithCapacity:[expr length] + 10];
+
+ [result appendString:quote];
+ [result appendString:[components componentsJoinedByString:escape]];
+ [result appendString:quote];
+
+ return AUTORELEASE(result);
+}
+
+- (id)initWithExpression:(id)_expression
+ quote:(NSString *)_quote
+ escape:(NSString *)_escape
+{
+ if ((self = [super init])) {
+ ASSIGN(self->expression, _expression);
+ ASSIGN(self->quote, _quote);
+ ASSIGN(self->escape, _escape);
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->expression);
+ RELEASE(self->quote);
+ RELEASE(self->escape);
+ [super dealloc];
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone {
+ return [[[self class]
+ allocWithZone:zone]
+ initWithExpression:expression quote:quote escape:escape];
+}
+- (id)copy {
+ return [self copyWithZone:NSDefaultMallocZone()];
+}
+
+@end /* EOQuotedExpression */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EORecordDictionary.m 1 2004-08-20 10:38:46Z znek $
+
+#include <stdarg.h>
+#include <math.h>
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSArray.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSException.h>
+
+#if LIB_FOUNDATION_LIBRARY
+# include <Foundation/exceptions/GeneralExceptions.h>
+# include <extensions/objc-runtime.h>
+#else
+# include <NGExtensions/NGObjectMacros.h>
+#endif
+
+#include "EORecordDictionary.h"
+
+@implementation EORecordDictionary
+
+static NSDictionary *emptyDict = nil;
+
+- (id)init {
+ RELEASE(self);
+ if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init];
+ return [emptyDict retain];
+}
+
+- (id)initWithObjects:(id *)_objects forKeys:(id *)_keys
+ count:(unsigned int)_count
+{
+ if (_count == 0) {
+ RELEASE(self);
+ if (emptyDict == nil) emptyDict = [[NSDictionary alloc] init];
+ return [emptyDict retain];
+ }
+
+ if (_count == 1) {
+ RELEASE(self);
+ return [[NSDictionary alloc]
+ initWithObjects:_objects forKeys:_keys
+ count:_count];
+ }
+
+ self->count = _count;
+ while(_count--) {
+ if ((_keys[_count] == nil) || (_objects[_count] == nil)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Nil object to be added in dictionary"];
+ }
+ self->entries[_count].key = RETAIN(_keys[_count]);
+ self->entries[_count].hash = [_keys[_count] hash];
+ self->entries[_count].value = RETAIN(_objects[_count]);
+ }
+ return self;
+}
+
+- (id)initWithDictionary:(NSDictionary *)dictionary {
+ // TODO: who calls this method?
+ NSEnumerator *keys;
+ unsigned char i;
+
+ keys = [dictionary keyEnumerator];
+ self->count = [dictionary count];
+
+ for (i = 0; i < self->count; i++) {
+ id key = [keys nextObject];
+
+ self->entries[i].key = RETAIN(key);
+ self->entries[i].hash = [key hash];
+ self->entries[i].value = RETAIN([dictionary objectForKey:key]);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ /* keys are always NSString keys?! */
+#if GNU_RUNTIME
+ static Class LastKeyClass = Nil;
+ static IMP keyRelease = 0;
+ static unsigned misses = 0, hits = 0;
+#endif
+ register unsigned char i;
+
+ for (i = 0; i < self->count; i++) {
+ register NSString *key = self->entries[i].key;
+#if GNU_RUNTIME
+ if (*(id *)key != LastKeyClass) {
+ LastKeyClass = *(id *)key;
+ keyRelease =
+ method_get_imp(class_get_instance_method(LastKeyClass,
+ @selector(release)));
+ misses++;
+ }
+ else
+ hits++;
+
+ keyRelease(key, NULL /* dangerous? */);
+
+#if PROF_METHOD_CACHE
+ if (hits % 1000 == 0 && hits != 0)
+ NSLog(@"%s: DB HITS: %d MISSES: %d", __PRETTY_FUNCTION__,hits, misses);
+#endif
+#else
+ [key release];
+#endif
+
+ RELEASE(self->entries[i].value);
+ }
+ [super dealloc];
+}
+
+/* operations */
+
+- (id)objectForKey:(id)aKey {
+ register EORecordDictionaryEntry *e = self->entries;
+ register signed char i;
+ register unsigned hash;
+#if GNU_RUNTIME
+ static Class LastKeyClass = Nil;
+ static unsigned (*keyHash)(id,SEL) = 0;
+ static BOOL (*keyEq)(id,SEL,id) = 0;
+#if PROF_METHOD_CACHE
+ static unsigned misses = 0, hits = 0;
+#endif
+#endif
+
+#if GNU_RUNTIME
+ if (aKey == nil)
+ return nil;
+
+ if (*(id *)aKey != LastKeyClass) {
+ LastKeyClass = *(id *)aKey;
+ keyHash = (void *)
+ method_get_imp(class_get_instance_method(LastKeyClass,
+ @selector(hash)));
+ keyEq = (void *)
+ method_get_imp(class_get_instance_method(LastKeyClass,
+ @selector(isEqual:)));
+ }
+
+ hash = keyHash(aKey, NULL /* dangerous? */);
+#else
+ hash = [aKey hash];
+#endif
+
+ for (i = (self->count - 1); i >= 0; i--, e++) {
+ if (e->hash != hash)
+ continue;
+ if (e->key == aKey)
+ return e->value;
+
+#if GNU_RUNTIME
+ if (keyEq(e->key, NULL /* dangerous? */, aKey))
+ return e->value;
+#else
+ if ([e->key isEqual:aKey])
+ return e->value;
+#endif
+ }
+ return nil;
+}
+
+- (unsigned int)count {
+ return self->count;
+}
+- (NSEnumerator *)keyEnumerator {
+ return AUTORELEASE([[_EORecordDictionaryKeyEnumerator alloc]
+ initWithDictionary:self
+ firstEntry:self->entries count:self->count]);
+}
+
+@end /* NSConcreteSmallDictionary */
+
+@implementation _EORecordDictionaryKeyEnumerator
+
+- (id)initWithDictionary:(EORecordDictionary *)_dict
+ firstEntry:(EORecordDictionaryEntry *)_firstEntry
+ count:(unsigned char)_count
+{
+ self->dict = RETAIN(_dict);
+ self->currentEntry = _firstEntry;
+ self->count = _count;
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->dict);
+ [super dealloc];
+}
+
+- (id)nextObject {
+ if (self->count > 0) {
+ id obj;
+ obj = self->currentEntry->key;
+ self->currentEntry++;
+ self->count--;
+ return obj;
+ }
+
+ return nil;
+}
+
+@end /* _NSConcreteSmallDictionaryKeyEnumerator */
--- /dev/null
+/*
+ EORelationship.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: August 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "common.h"
+#import "EOModel.h"
+#import "EOAttribute.h"
+#import "EOEntity.h"
+#import "EORelationship.h"
+#import "EOExpressionArray.h"
+#import "EOFExceptions.h"
+#import <EOControl/EONull.h>
+
+static EONull *null = nil;
+
+@interface EOJoin : EORelationship // for adaptor compability
+@end
+
+@implementation EORelationship
+
++ (void)initialize {
+ if (null == nil) null = [[EONull null] retain];
+}
+
+- (id)init {
+ if ((self = [super init])) {
+ self->flags.createsMutableObjects = YES;
+ self->entity = nil;
+ self->destinationEntity = nil;
+ }
+ return self;
+}
+
+- (id)initWithName:(NSString*)_name {
+ if ((self = [self init])) {
+ self->name = _name;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->name);
+ RELEASE(self->definition);
+ RELEASE(self->userDictionary);
+ self->entity = nil;
+ if ([self->destinationEntity isKindOfClass:[NSString class]])
+ RELEASE(self->destinationEntity);
+ // else: non-retained EOEntity
+ self->destinationEntity = nil;
+ RELEASE(self->componentRelationships);
+ RELEASE(self->sourceAttribute);
+ RELEASE(self->destinationAttribute);
+ [super dealloc];
+}
+
+// These methods should be here to let the library work with NeXT foundation
+- (id)copy {
+ return RETAIN(self);
+}
+- (id)copyWithZone:(NSZone *)_zone {
+ return RETAIN(self);
+}
+
+// Is equal only if same name; used to make aliasing ordering stable
+- (unsigned)hash {
+ return [self->name hash];
+}
+
++ (BOOL)isValidName:(NSString*)_name {
+ return [EOEntity isValidName:_name];
+}
+
+- (void)setDefinition:(NSString *)def {
+ if (def == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"invalid (nil) definition argument ..."];
+ }
+
+ if ([def isNameOfARelationshipPath]) {
+ NSArray *defArray = nil;
+ int count;
+
+ defArray = [def componentsSeparatedByString:@"."];
+ count = [defArray count];
+
+ RELEASE(self->componentRelationships);
+ self->componentRelationships =
+ [[NSMutableArray alloc] initWithCapacity:count];
+
+ flags.isFlattened = YES;
+
+ NS_DURING {
+ EOEntity *currentEntity = self->entity;
+ id relationship = nil;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ id relationshipName = [defArray objectAtIndex:i];
+
+ /* Take the address of `relationship' to force the compiler
+ to not allocate it into a register. */
+ *(&relationship) = [currentEntity relationshipNamed:
+ relationshipName];
+ if (!relationship)
+ [[[InvalidPropertyException alloc]
+ initWithName:relationshipName
+ entity:currentEntity] raise];
+ [self->componentRelationships addObject:relationship];
+ flags.isToMany |= [relationship isToMany];
+ currentEntity = [relationship destinationEntity];
+ }
+ if (self->destinationEntity &&
+ ![self->destinationEntity isEqual:currentEntity])
+ [[[DestinationEntityDoesntMatchDefinitionException alloc]
+ initForDestination:self->destinationEntity
+ andDefinition:def
+ relationship:self] raise];
+ if ([self->destinationEntity isKindOfClass:[NSString class]])
+ RELEASE(self->destinationEntity);
+ self->destinationEntity = currentEntity; /* non-retained */
+ if ([self->destinationEntity isKindOfClass:[NSString class]])
+ RETAIN(self->destinationEntity);
+ }
+ NS_HANDLER {
+ RELEASE(self->componentRelationships);
+ self->componentRelationships = nil;
+ [localException raise];
+ }
+ NS_ENDHANDLER;
+ }
+ else
+ [[[InvalidNameException alloc] initWithName:def] raise];
+
+ ASSIGN(self->definition, def);
+}
+
+- (BOOL)setToMany:(BOOL)_flag {
+ if ([self isFlattened]) return NO;
+ self->flags.isToMany = _flag;
+ return YES;
+}
+- (BOOL)isToMany {
+ return self->flags.isToMany;
+}
+
+- (BOOL)setName:(NSString *)_name {
+ if ([self->entity referencesProperty:_name])
+ return NO;
+ ASSIGN(self->name, _name);
+ return NO;
+}
+- (NSString *)name {
+ return self->name;
+}
+
+- (BOOL)isCompound {
+ return NO;
+}
+
+- (NSString *)expressionValueForContext:(id<EOExpressionContext>)_ctx {
+ return self->name;
+}
+
+- (void)setEntity:(EOEntity *)_entity {
+ self->entity = _entity; /* non-retained */
+}
+- (EOEntity *)entity {
+ return self->entity;
+}
+- (void)resetEntities {
+ self->entity = nil;
+ self->destinationEntity = nil;
+}
+- (BOOL)hasEntity {
+ return (self->entity != nil) ? YES : NO;
+}
+- (BOOL)hasDestinationEntity {
+ return (self->destinationEntity != nil) ? YES : NO;
+}
+
+- (void)setUserDictionary:(NSDictionary *)dict {
+ ASSIGN(self->userDictionary, dict);
+}
+- (NSDictionary *)userDictionary {
+ return self->userDictionary;
+}
+
+- (NSArray *)joins {
+ return self->sourceAttribute ? [NSArray arrayWithObject:self] : nil;
+}
+
+- (NSString *)definition {
+ return self->definition;
+}
+- (NSArray *)sourceAttributes {
+ return [NSArray arrayWithObject:self->sourceAttribute];
+}
+- (NSArray *)destinationAttributes {
+ return [NSArray arrayWithObject:self->destinationAttribute];
+}
+- (EOEntity *)destinationEntity {
+ return self->destinationEntity;
+}
+- (BOOL)isFlattened {
+ return self->flags.isFlattened;
+}
+- (NSArray *)componentRelationships {
+ return self->componentRelationships;
+}
+
+- (BOOL)referencesProperty:(id)_property {
+ if ([self->sourceAttribute isEqual:_property])
+ return YES;
+ if ([self->destinationAttribute isEqual:_property])
+ return YES;
+
+ if ([self->componentRelationships indexOfObject:_property] != NSNotFound)
+ return YES;
+ return NO;
+}
+
+- (NSDictionary *)foreignKeyForRow:(NSDictionary *)_row {
+ int j, i, n = [_row count];
+ id keys[n], vals[n];
+
+ for (i = j = 0, n = 1; j < n; j++) {
+ EOAttribute *keyAttribute = self->sourceAttribute;
+ EOAttribute *fkeyAttribute = self->destinationAttribute;
+ NSString *key = nil;
+ NSString *fkey = nil;
+ id value = nil;
+
+ key = [keyAttribute name];
+ fkey = [fkeyAttribute name];
+ value = [_row objectForKey:key];
+
+ if (value) {
+ vals[i] = value;
+ keys[i] = fkey;
+ i++;
+ }
+ else {
+ NSLog(@"%s: could not get value of key %@ (foreignKey=%@)",
+ __PRETTY_FUNCTION__, key, fkey);
+ }
+ }
+
+ return AUTORELEASE([[NSDictionary alloc]
+ initWithObjects:vals
+ forKeys:keys count:i]);
+}
+
+- (NSString *)description {
+ return [[self propertyList] description];
+}
+
+@end /* EORelationship */
+
+
+@implementation EORelationship (EORelationshipPrivate)
+
++ (EORelationship *)relationshipFromPropertyList:(id)_plist
+ model:(EOModel *)model
+{
+ EORelationship *relationship = nil;
+ NSArray *array = nil;
+ NSEnumerator *enumerator = nil;
+ id joinPList = nil;
+
+ relationship = AUTORELEASE([EORelationship new]);
+ [relationship setCreateMutableObjects:YES];
+ [relationship setName:[_plist objectForKey:@"name"]];
+ [relationship setUserDictionary:
+ [_plist objectForKey:@"userDictionary"]];
+
+ if ((array = [_plist objectForKey:@"joins"])) {
+ enumerator = [array objectEnumerator];
+
+ joinPList = [enumerator nextObject];
+ [relationship loadJoinPropertyList:joinPList];
+ joinPList = [enumerator nextObject];
+ NSAssert(joinPList == nil, @"a relationship only supports one join !");
+ }
+ else {
+ [relationship loadJoinPropertyList:_plist];
+ }
+
+ relationship->destinationEntity =
+ RETAIN([_plist objectForKey:@"destination"]);
+ // retained string
+
+ relationship->flags.isToMany =
+ [[_plist objectForKey:@"isToMany"] isEqual:@"Y"];
+
+ relationship->flags.isMandatory =
+ [[_plist objectForKey:@"isMandatory"] isEqual:@"Y"];
+
+ /* Do not send here the -setDefinition: message because the relationships
+ are not yet created from the model file. */
+ relationship->definition
+ = RETAIN([_plist objectForKey:@"definition"]);
+
+ return relationship;
+}
+
+- (void)replaceStringsWithObjects {
+ EOModel *model = [self->entity model];
+
+ if (self->destinationEntity) {
+ // now self->destinationEntity is NSString and retained !!
+ id destinationEntityName = AUTORELEASE(self->destinationEntity);
+ self->destinationEntity = [model entityNamed:destinationEntityName];
+ // now hold entity non-retained
+
+ if (self->destinationEntity == nil) {
+ NSLog(@"invalid entity name '%@' specified as destination entity "
+ @"for relationship '%@' in entity '%@'",
+ destinationEntityName, name, [self->entity name]);
+ [model errorInReading];
+ }
+ }
+
+ if (!(self->destinationEntity || self->definition)) {
+ NSLog(@"relationship '%@' in entity '%@' is incompletely specified: "
+ @"no destination entity or definition.", name, [self->entity name]);
+ [model errorInReading];
+ }
+
+ if (self->definition && (self->sourceAttribute != nil)) {
+ NSLog(@"relationship '%@' in entity '%@': flattened relationships "
+ @"cannot have joins", name, [self->entity name]);
+ [model errorInReading];
+ }
+
+ if (self->sourceAttribute) {
+ EOEntity *attributeEntity;
+ EOAttribute *attribute = nil;
+
+#if 0
+ attributeEntity = self->flags.isToMany
+ ? self->destinationEntity
+ : self->entity;
+#endif
+ attributeEntity = self->entity;
+ attribute =
+ [attributeEntity attributeNamed:(NSString*)self->sourceAttribute];
+
+ if (attribute)
+ [self setSourceAttribute:attribute];
+ else {
+ [model errorInReading];
+ NSLog(@"invalid attribute name '%@' specified as source attribute for "
+ @"join in relationship '%@' in entity '%@' (dest='%@')",
+ sourceAttribute, [self name],
+ [self->entity name], [self->destinationEntity name]);
+ }
+
+#if 0
+ attributeEntity = self->flags.isToMany
+ ? self->entity
+ : self->destinationEntity;
+#endif
+ attributeEntity = self->destinationEntity;
+ attribute = [attributeEntity attributeNamed:(NSString*)destinationAttribute];
+
+ if (attribute)
+ [self setDestinationAttribute:attribute];
+ else {
+ [model errorInReading];
+ NSLog(@"invalid attribute name '%@' specified as destination "
+ @"attribute for join in relationship '%@' in entity '%@' (dest='%@')",
+ destinationAttribute, [self name],
+ [self->entity name], [self->destinationEntity name]);
+ }
+ }
+ [self setCreateMutableObjects:NO];
+}
+
+- (void)initFlattenedRelationship {
+ if (self->definition) {
+ NS_DURING
+ [self setDefinition:self->definition];
+ NS_HANDLER {
+ NSLog([localException reason]);
+ [[self->entity model] errorInReading];
+ }
+ NS_ENDHANDLER;
+ }
+}
+
+- (id)propertyList {
+ NSMutableDictionary *propertyList = nil;
+
+ propertyList = [NSMutableDictionary dictionary];
+ [self encodeIntoPropertyList:propertyList];
+ return propertyList;
+}
+
+- (void)setCreateMutableObjects:(BOOL)flag {
+ if (self->flags.createsMutableObjects == flag)
+ return;
+
+ self->flags.createsMutableObjects = flag;
+}
+
+- (BOOL)createsMutableObjects {
+ return self->flags.createsMutableObjects;
+}
+
+- (int)compareByName:(EORelationship *)_other {
+ return [[(EORelationship *)self name] compare:[_other name]];
+}
+
+@end /* EORelationship (EORelationshipPrivate) */
+
+@implementation EORelationship(EOJoin)
+
+- (void)loadJoinPropertyList:(id)propertyList {
+ NSString *joinOperatorPList;
+ NSString *joinSemanticPList;
+ id tmp;
+
+ tmp = [propertyList objectForKey:@"sourceAttribute"];
+ [self setSourceAttribute:tmp];
+ tmp = [propertyList objectForKey:@"destinationAttribute"];
+ [self setDestinationAttribute:tmp];
+
+ if ((joinOperatorPList = [propertyList objectForKey:@"joinOperator"])) {
+ NSAssert([joinOperatorPList isEqual:@"EOJoinEqualTo"],
+ @"only EOJoinEqualTo is supported as the join operator !");
+ }
+
+ if ((joinSemanticPList = [propertyList objectForKey:@"joinSemantic"])) {
+ NSAssert([joinSemanticPList isEqual:@"EOInnerJoin"],
+ @"only EOInnerJoin is supported as the join semantic !");
+ }
+}
+
+- (void)setDestinationAttribute:(EOAttribute*)attribute {
+ ASSIGN(self->destinationAttribute, attribute);
+}
+- (EOAttribute*)destinationAttribute {
+ return self->destinationAttribute;
+}
+
+- (void)setSourceAttribute:(EOAttribute *)attribute {
+ ASSIGN(self->sourceAttribute, attribute);
+}
+- (EOAttribute*)sourceAttribute {
+ return self->sourceAttribute;
+}
+
+- (EOJoinOperator)joinOperator {
+ return EOJoinEqualTo;
+}
+- (EOJoinSemantic)joinSemantic {
+ return EOInnerJoin;
+}
+
+- (EORelationship*)relationship {
+ return self;
+}
+
+// misc
+
+- (void)addJoin:(EOJoin *)_join {
+ [self setSourceAttribute:[_join sourceAttribute]];
+ [self setDestinationAttribute:[_join destinationAttribute]];
+}
+
+@end /* EORelationship(EOJoin) */
+
+@implementation EORelationship(PropertyListCoding)
+
+static inline void _addToPropList(NSMutableDictionary *_plist,
+ id _value, NSString *key) {
+ if (_value) [_plist setObject:_value forKey:key];
+}
+
+- (void)encodeIntoPropertyList:(NSMutableDictionary *)_plist {
+ _addToPropList(_plist, self->name, @"name");
+ _addToPropList(_plist, self->definition, @"definition");
+ _addToPropList(_plist, self->userDictionary, @"userDictionary");
+
+ if (self->sourceAttribute) { // has join ?
+ _addToPropList(_plist, [self->sourceAttribute name], @"sourceAttribute");
+ _addToPropList(_plist, [self->destinationAttribute name],
+ @"destinationAttribute");
+ _addToPropList(_plist, [[self->sourceAttribute entity] name],
+ @"destination");
+ }
+
+ if (![self isFlattened] && self->destinationEntity) {
+ _addToPropList(_plist, [self->destinationEntity name], @"destination");
+ }
+
+ if (![self isFlattened])
+ _addToPropList(_plist, flags.isToMany ? @"Y" : @"N", @"isToMany");
+
+ if (![self isMandatory])
+ _addToPropList(_plist, flags.isMandatory ? @"Y" : @"N", @"isMandatory");
+}
+
+@end /* EORelationship(PropertyListCoding) */
+
+@implementation EORelationship(EOF2Additions)
+
+/* constraints */
+
+- (void)setIsMandatory:(BOOL)_flag {
+ self->flags.isMandatory = _flag ? 1 : 0;
+}
+- (BOOL)isMandatory {
+ return self->flags.isMandatory ? YES : NO;
+}
+
+- (NSException *)validateValue:(id *)_value {
+ if (_value == NULL) return nil;
+
+ /* check 'mandatory' constraint */
+
+ if (self->flags.isMandatory) {
+ if (self->flags.isToMany) {
+ if ([*_value count] == 0) {
+ NSLog(@"WARNING(%s): tried to use value %@"
+ @"with mandatory toMany relationship %@",
+ __PRETTY_FUNCTION__, *_value, self);
+ }
+ }
+ else {
+ if ((*_value == nil) || (*_value == null)) {
+ NSLog(@"WARNING(%s): tried to use value %@"
+ @"with mandatory toOne relationship %@",
+ __PRETTY_FUNCTION__, *_value, self);
+ }
+ }
+ }
+
+ return nil;
+}
+
+@end /* EORelationship(EOF2Additions) */
+
+@implementation EOJoin
+@end /* EOJoin */
--- /dev/null
+/*
+ EOSQLExpression.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: September 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "EOSQLExpression.h"
+#include "common.h"
+#import "EOAdaptor.h"
+#import "EOAdaptorChannel.h"
+#import "EOAdaptorContext.h"
+#import "EOAttribute.h"
+#import "EOAttributeOrdering.h"
+#import "EOEntity.h"
+#import "EOFExceptions.h"
+#import "EOSQLQualifier.h"
+#import "EORelationship.h"
+#import <EOControl/EOFetchSpecification.h>
+#import <EOControl/EONull.h>
+#import <EOControl/EOQualifier.h>
+#import <EOControl/EOSortOrdering.h>
+
+#if LIB_FOUNDATION_LIBRARY
+# include <extensions/DefaultScannerHandler.h>
+# include <extensions/PrintfFormatScanner.h>
+#else
+# include "DefaultScannerHandler.h"
+# include "PrintfFormatScanner.h"
+#endif
+
+/*
+A SQL command is generated for an entity when you fetch, insert, update or
+delete an object from the database. The command includes all the attributes
+from entity.
+
+The biggest problem in generation of SQL commands is the generation of SELECT
+statements, because the tables have to be properly aliased. If an entity has
+only simple attributes then you have a single table in the FROM clause. If the
+entity has flattened attributes, then several tables appear in the FROM list;
+each one with a different alias.
+
+The algorithm uses a dictionary that has as keys either entities or
+relationships. The values in dictionary are aliases.
+
+For a simple attribute we insert in the above dictionary the attribute's entity
+as key and an alias for it.
+
+For a flattened attribute with the following definition: `toEntity1.toEntity2.
+... toEntityn.attribute', we have to assign to each toEntityi object an alias.
+
+Let's see how each component of the SELECT command is generated. The columns
+list is generated by iterating over the attributes of entity. If the attribute
+is simple, its entity is looked up in the aliases dictionary. If the attribute
+is flattened, the alias of attribute is the alias of toEntityn. If the
+attribute is derived, each component of it is generated applying the same
+rules.
+
+The FROM list is generated like this. For each key in the aliases dictionary:
+* if the key is an entity, its external name is written followed by the alias
+corresponding to entity
+* if the key is a relationship, the external name of its destination entity is
+written followed by the alias corresponding to relationship.
+
+A little bit complicated is the WHERE clause. For each flattened attribute we
+have to generate the logic expression that selects the attribute by expressing
+the joins over several entities. The algorithm starts with the first
+relationship. An additional variable, named context is used. Its initial value
+is the current entity. The expression
+
+context-alias.source-attribute join-operator
+ relationship-alias.destination-attribute
+
+is added using the AND operator to the where clause. Then the context variable
+is set to the current relationship. The algorithm continues with the next
+relationship until there are no more relationships to process.
+
+*/
+
+static EONull *null = nil;
+NSString *EOBindVariableNameKey = @"name";
+NSString *EOBindVariablePlaceHolderKey = @"placeHolder";
+NSString *EOBindVariableAttributeKey = @"attribute";
+NSString *EOBindVariableValueKey = @"value";
+
+
+@interface EOInsertUpdateScannerHandler : DefaultScannerHandler
+{
+ NSString *value;
+ EOAttribute *attribute;
+ EOAdaptor *adaptor;
+}
+
+- (void)setValue:(NSString*)value
+ attribute:(EOAttribute*)attribute
+ adaptor:(EOAdaptor*)adaptor;
+@end
+
+
+@implementation EOInsertUpdateScannerHandler
+
+- (id)init {
+ [super init];
+
+ specHandler['V']
+ = [self methodForSelector:@selector(convertValue:scanner:)];
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->value);
+ RELEASE(self->attribute);
+ RELEASE(self->adaptor);
+ [super dealloc];
+}
+
+- (void)setValue:(NSString *)_value
+ attribute:(EOAttribute*)_attribute
+ adaptor:(EOAdaptor*)_adaptor
+{
+ ASSIGNCOPY(self->value, _value);
+ ASSIGN(self->attribute, _attribute);
+ ASSIGN(self->adaptor, _adaptor);
+}
+
+- (NSString *)convertValue:(va_list *)pString scanner:(FormatScanner *)scanner{
+ return (self->adaptor)
+ ? [self->adaptor formatValue:self->value?self->value:(id)null
+ forAttribute:attribute]
+ : self->value;
+}
+
+@end /* EOInsertUpdateScannerHandler */
+
+
+@implementation EOSQLExpression
+
++ (int)version {
+ return 1;
+}
+
++ (void)initialize {
+ if (null == nil) null = [[NSNull null] retain];
+}
+
+- (id)initWithEntity:(EOEntity *)_entity {
+ if ((self = [super init])) {
+ ASSIGN(self->entity, _entity);
+ }
+ return self;
+}
+- (id)init {
+ return [self initWithEntity:nil];
+}
+
++ (id)deleteExpressionWithQualifier:(EOSQLQualifier*)qualifier
+ channel:(EOAdaptorChannel*)channel
+{
+ EOSQLExpression* sqlExpression
+ = AUTORELEASE([[self deleteExpressionClass] new]);
+ [sqlExpression deleteExpressionWithQualifier:qualifier channel:channel];
+ return sqlExpression;
+}
++ (id)insertExpressionForRow:(NSDictionary *)row
+ entity:(EOEntity*)_entity
+ channel:(EOAdaptorChannel*)channel
+{
+ EOSQLExpression* sqlExpression
+ = AUTORELEASE([[self insertExpressionClass] new]);
+
+ [sqlExpression insertExpressionForRow:row entity:_entity channel:channel];
+ return sqlExpression;
+}
+
+- (id)deleteExpressionWithQualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel*)channel
+{
+ NSString *sql;
+
+ self = [self initWithEntity:[qualifier entity]];
+
+ self->adaptor = RETAIN([[channel adaptorContext] adaptor]);
+
+ sql = [self assembleDeleteStatementWithQualifier:qualifier
+ tableList:[entity externalName]
+ whereClause:[self whereClauseForQualifier:qualifier]];
+
+ self->content = [sql mutableCopy];
+ [self finishBuildingExpression];
+
+ return self;
+}
+
+- (id)insertExpressionForRow:(NSDictionary *)row
+ entity:(EOEntity*)_entity
+ channel:(EOAdaptorChannel*)channel
+{
+ NSString *sql;
+
+ self = [self initWithEntity:_entity];
+
+ self->adaptor = RETAIN([[channel adaptorContext] adaptor]);
+
+ sql = [self assembleInsertStatementWithRow:row
+ tableList:[entity externalName]
+ columnList:[self columnListForRow:row]
+ valueList:[self valueListForRow:row]];
+
+ self->content = [sql mutableCopy];
+
+ [self finishBuildingExpression];
+
+ return self;
+}
+
++ (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel
+{
+ EOSQLExpression* sqlExpression
+ = AUTORELEASE([[self selectExpressionClass] new]);
+ [sqlExpression selectExpressionForAttributes:attributes
+ lock:flag
+ qualifier:qualifier
+ fetchOrder:fetchOrder
+ channel:channel];
+ return sqlExpression;
+}
+
+- (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel
+{
+ NSArray *relationshipPaths;
+ NSString *sql;
+
+ self = [self initWithEntity:[qualifier entity]];
+
+ self->adaptor = [[[channel adaptorContext] adaptor] retain];
+ // self->content = [NSMutableString new]; // mh: BUG!!!
+
+ relationshipPaths = [self relationshipPathsForAttributes:attributes
+ qualifier:qualifier
+ fetchOrder:fetchOrder];
+
+ sql = [self assembleSelectStatementWithAttributes:attributes
+ lock:flag
+ qualifier:qualifier
+ fetchOrder:fetchOrder
+ selectString:
+ [qualifier usesDistinct] ? @"SELECT DISTINCT" : @"SELECT"
+ columnList:
+ [self selectListWithAttributes:attributes
+ qualifier:qualifier]
+ tableList:[self fromClause]
+ whereClause:[self whereClauseForQualifier:qualifier]
+ joinClause:
+ [self joinExpressionForRelationshipPaths:relationshipPaths]
+ orderByClause:[self orderByClauseForFetchOrder:fetchOrder]
+ lockClause:flag ? [self lockClause] : nil];
+
+ self->content = [sql mutableCopy];
+
+ [self finishBuildingExpression];
+
+ return self;
+}
++ (id)updateExpressionForRow:(NSDictionary *)row
+ qualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel *)channel
+{
+ EOSQLExpression* sqlExpression
+ = AUTORELEASE([[self updateExpressionClass] new]);
+ [sqlExpression updateExpressionForRow:row
+ qualifier:qualifier
+ channel:channel];
+ return sqlExpression;
+}
+
+- (id)updateExpressionForRow:(NSDictionary *)row
+ qualifier:(EOSQLQualifier *)qualifier
+ channel:(EOAdaptorChannel *)channel
+{
+ NSString *sql;
+
+ self = [self initWithEntity:[qualifier entity]];
+ if (self->entity == nil) {
+ [[[InvalidQualifierException alloc]
+ initWithFormat:@"entity for qualifier %@ is nil",
+ [qualifier expressionValueForContext:nil]] raise];
+ }
+
+ self->adaptor = [[[channel adaptorContext] adaptor] retain];
+ self->content = [[NSMutableString alloc] init];
+
+ sql = [self assembleUpdateStatementWithRow:row
+ qualifier:qualifier
+ tableList:[entity externalName]
+ updateList:[self updateListForRow:row]
+ whereClause:[self whereClauseForQualifier:qualifier]];
+ [self->content appendString:sql];
+
+ [self finishBuildingExpression];
+
+ return self;
+}
+
+- (void)dealloc {
+ RELEASE(self->bindings);
+ RELEASE(self->listString);
+ RELEASE(self->whereClauseString);
+ RELEASE(self->entity);
+ RELEASE(self->adaptor);
+ RELEASE(self->entitiesAndPropertiesAliases);
+ RELEASE(self->fromListEntities);
+ RELEASE(self->content);
+ [super dealloc];
+}
+
+- (NSString *)selectListWithAttributes:(NSArray *)attributes
+ qualifier:(EOSQLQualifier *)qualifier
+{
+ NSMutableString *selectList;
+ NSEnumerator *enumerator;
+ BOOL first = YES;
+ EOAttribute *attribute;
+ BOOL isDistinct;
+
+ selectList = [NSMutableString stringWithCapacity:128];
+ isDistinct = [qualifier usesDistinct];
+
+ /* check whether DISTINCT is allowed */
+ enumerator = [attributes objectEnumerator];
+ while ((attribute = [enumerator nextObject])) {
+ if (self->adaptor) {
+ if (![self->adaptor attributeAllowedInDistinctSelects:attribute]) {
+#if DEBUG && 0
+ NSLog(@"WARNING: tried to select attribute type %@ with DISTINCT "
+ @"which is not allowed, disabling DISTINCT: %@",
+ [attribute externalType], [attribute name]);
+#endif
+ isDistinct = NO;
+ break;
+ }
+ }
+ }
+
+ enumerator = [attributes objectEnumerator];
+ while ((attribute = [enumerator nextObject])) {
+ if(first)
+ first = NO;
+ else
+ [selectList appendString:@", "];
+
+ [selectList appendString:[self expressionValueForAttribute:attribute]];
+ }
+
+ return selectList;
+}
+
+- (NSString *)fromClause {
+ NSMutableString *fromClause;
+ NSEnumerator *enumerator;
+ BOOL first = YES;
+ id key;
+
+ fromClause = [NSMutableString stringWithCapacity:64];
+ enumerator = [self->fromListEntities objectEnumerator];
+
+ /* Compute the FROM list from all the aliases found in
+ entitiesAndPropertiesAliases dictionary. Note that this dictionary
+ contains entities and relationships. The last ones are there for
+ flattened attributes over reflexive relationships. */
+ while ((key = [enumerator nextObject])) {
+ if (first)
+ first = NO;
+ else
+ [fromClause appendString:@", "];
+
+ if ([key isKindOfClass:[EORelationship class]]) {
+ /* This key corresponds to a flattened attribute. */
+ [fromClause appendFormat:@"%@ %@",
+ [[key destinationEntity] externalName],
+ [entitiesAndPropertiesAliases objectForKey:key]];
+ }
+ else {
+ /* This is an EOEntity. */
+ [fromClause appendFormat:@"%@ %@",
+ [key externalName],
+ [entitiesAndPropertiesAliases objectForKey:key]];
+ }
+ }
+
+ return fromClause;
+}
+
+- (NSString *)whereClauseForQualifier:(EOSQLQualifier *)_qualifier {
+ return [_qualifier expressionValueForContext:self];
+}
+
+- (id)joinExpressionForRelationshipPaths:(NSArray *)relationshipPaths
+{
+ NSMutableString *expression = [NSMutableString stringWithCapacity:64];
+ NSEnumerator *enumerator = [relationshipPaths objectEnumerator];
+ NSMutableArray *rels = [NSMutableArray new];
+ NSArray *relationshipPath;
+ EORelationship *relationship;
+ BOOL first = YES;
+
+ while ((relationshipPath = [enumerator nextObject])) {
+ NSEnumerator *componentRelationshipsEnumerator;
+ id context;
+
+ componentRelationshipsEnumerator = [relationshipPath objectEnumerator];
+ context = entity;
+
+ while((relationship = [componentRelationshipsEnumerator nextObject])) {
+ if (![rels containsObject:relationship]) {
+ id sourceAttribute, destinationAttribute;
+
+ [rels addObject:relationship];
+
+ /* Compute the SQL expression string corresponding to each join in
+ the relationship. */
+ sourceAttribute = [self expressionValueForAttribute:
+ [relationship sourceAttribute]
+ context:context];
+ destinationAttribute = [self expressionValueForAttribute:
+ [relationship destinationAttribute]
+ context:
+ [relationship destinationEntity]];
+
+ //NSLog(@"sourceAttribute %@", sourceAttribute);
+ //NSLog(@"destinationAttribute %@", destinationAttribute);
+
+ if (first)
+ first = NO;
+ else
+ [expression appendString:@" AND "];
+
+ [expression appendString:[sourceAttribute description]];
+ [expression appendString:@" = "];
+ [expression appendString:[destinationAttribute description]];
+ }
+ /* Compute the next context which is the current relationship. */
+ context = [relationship destinationEntity];
+ }
+ }
+ [rels release];
+ return expression;
+}
+
+- (NSString *)orderByClauseForFetchOrder:(NSArray *)fetchOrder
+{
+ int i, count;
+ NSMutableString *orderBy;
+
+ if ((count = [fetchOrder count]) == 0)
+ return @"";
+
+ orderBy = (id)[NSMutableString stringWithCapacity:32];
+ for(i = 0; i < count; i++) {
+ id eorder;
+
+ eorder = [fetchOrder objectAtIndex:i];
+
+ if (i != 0) [orderBy appendString:@", "];
+
+ if ([eorder isKindOfClass:[EOSortOrdering class]]) {
+ EOSortOrdering *order;
+ EOAttribute *attribute;
+ SEL ordering;
+ NSString *fmt;
+
+ order = eorder;
+ ordering = [order selector];
+ attribute = [self->entity attributeNamed:[order key]];
+
+ if (sel_eq(ordering, EOCompareCaseInsensitiveAscending) ||
+ sel_eq(ordering, EOCompareCaseInsensitiveDescending))
+ fmt = @"LOWER(%@)";
+ else
+ fmt = @"%@";
+
+ [orderBy appendFormat:fmt, [self expressionValueForAttribute:attribute]];
+
+ if (sel_eq(ordering, EOCompareCaseInsensitiveAscending) ||
+ sel_eq(ordering, EOCompareAscending)) {
+ [orderBy appendString:@" ASC"];
+ }
+ else if (sel_eq(ordering, EOCompareCaseInsensitiveDescending) ||
+ sel_eq(ordering, EOCompareDescending)) {
+ [orderBy appendString:@" DESC"];
+ }
+ }
+ else {
+ EOAttributeOrdering *order;
+ EOOrdering ordering;
+
+ order = eorder;
+ ordering = [order ordering];
+
+ [orderBy appendFormat:@"%@",
+ [self expressionValueForAttribute:[order attribute]]];
+ if (ordering != EOAnyOrder)
+ [orderBy appendString:
+ ([order ordering] == EOAscendingOrder ? @" ASC" : @" DESC")];
+ }
+ }
+
+ return orderBy;
+}
+
+- (NSString *)literalForAttribute:(EOAttribute *)_attribute
+ withValue:(id)_value fromRow:(NSDictionary *)_row
+{
+ return (self->adaptor)
+ ? [self->adaptor formatValue:_value?_value:null forAttribute:_attribute]
+ : [_value stringValue];
+}
+
+- (id)updateListForRow:(NSDictionary *)row {
+ PrintfFormatScanner *formatScanner = nil;
+ EOInsertUpdateScannerHandler *scannerHandler = nil;
+ NSMutableString *expression = nil;
+ NSEnumerator *enumerator;
+ NSString *attributeName = nil;
+ BOOL first = YES;
+
+ enumerator = [row keyEnumerator];
+ expression = [NSMutableString stringWithCapacity:256];
+
+ formatScanner = [[PrintfFormatScanner alloc] init];
+ AUTORELEASE(formatScanner);
+ scannerHandler = [[EOInsertUpdateScannerHandler alloc] init];
+ AUTORELEASE(scannerHandler);
+
+ [formatScanner setAllowOnlySpecifier:YES];
+ [formatScanner setFormatScannerHandler:scannerHandler];
+
+ while((attributeName = [enumerator nextObject])) {
+ EOAttribute *attribute;
+ NSString *updateFormat;
+ NSString *columnName = nil;
+ id value = nil;
+
+ attribute = [entity attributeNamed:attributeName];
+ updateFormat = [attribute updateFormat];
+
+ NSAssert1(attribute, @"attribute %@ should be non nil", attributeName);
+ columnName = adaptor
+ ? [adaptor formatAttribute:attribute]
+ : [attribute columnName];
+
+ value = [row objectForKey:attributeName];
+
+ if (updateFormat) {
+ [scannerHandler setValue:value
+ attribute:attribute
+ adaptor:adaptor];
+#if defined(__s390__)
+ value = [formatScanner performSelector:
+ @selector(stringWithFormat:arguments:)
+ withObject:updateFormat
+ withObject:nil];
+#else
+ value = [formatScanner stringWithFormat:updateFormat
+ arguments:NULL];
+#endif
+ }
+ else {
+ value = [self literalForAttribute:attribute
+ withValue:value fromRow:row];
+ }
+
+ if(first) first = NO;
+ else [expression appendString:@", "];
+
+ [expression appendString:columnName];
+ [expression appendString:@" = "];
+ [expression appendString:value];
+ }
+
+ return expression;
+}
+
+- (id)columnListForRow:(NSDictionary *)row {
+ NSMutableString *expression;
+ NSEnumerator *enumerator;
+ NSString *attributeName = nil;
+ BOOL first = YES;
+
+ expression = [NSMutableString stringWithCapacity:128];
+ enumerator = [row keyEnumerator];
+
+ while ((attributeName = [enumerator nextObject])) {
+ EOAttribute *attribute;
+ NSString *columnName;
+
+ attribute = [entity attributeNamed:attributeName];
+
+ NSAssert1(attribute, @"attribute %@ should be non nil", attributeName);
+ columnName = adaptor
+ ? [adaptor formatAttribute:attribute]
+ : [attribute columnName];
+
+ if (first) first = NO;
+ else [expression appendString:@", "];
+
+ [expression appendString:columnName];
+ }
+
+ return expression;
+}
+
+- (id)valueListForRow:(NSDictionary *)row {
+ EOInsertUpdateScannerHandler *scannerHandler;
+ PrintfFormatScanner *formatScanner;
+ NSEnumerator *enumerator;
+ NSString *attributeName = nil;
+ NSMutableString *expression = nil;
+ BOOL first = YES;
+
+ formatScanner = [[PrintfFormatScanner alloc] init];
+ AUTORELEASE(formatScanner);
+ scannerHandler = [[EOInsertUpdateScannerHandler alloc] init];
+ AUTORELEASE(scannerHandler);
+
+ expression = [NSMutableString stringWithCapacity:256];
+ enumerator = [row keyEnumerator];
+
+ [formatScanner setAllowOnlySpecifier:YES];
+ [formatScanner setFormatScannerHandler:scannerHandler];
+
+ while ((attributeName = [enumerator nextObject])) {
+ EOAttribute *attribute;
+ NSString *insertFormat;
+ id value;
+
+ attribute = [entity attributeNamed:attributeName];
+ insertFormat = [attribute insertFormat];
+ value = [row objectForKey:attributeName];
+
+ NSAssert1(attribute, @"attribute %@ should be non nil", attributeName);
+ if (insertFormat) {
+ [scannerHandler setValue:value
+ attribute:attribute
+ adaptor:self->adaptor];
+#if defined(__s390__)
+ value = [formatScanner performSelector:
+ @selector(stringWithFormat:arguments:)
+ withObject:insertFormat
+ withObject:nil];
+#else
+ value = [formatScanner stringWithFormat:insertFormat
+ arguments:NULL];
+#endif
+ }
+ else {
+ value = [self literalForAttribute:attribute
+ withValue:value fromRow:row];
+ }
+
+ if(first) first = NO;
+ else [expression appendString:@", "];
+
+ [expression appendString:value];
+ }
+
+ return expression;
+}
+
+- (NSArray *)relationshipPathsForAttributes:(NSArray *)attributes
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+{
+ int i, count;
+ NSMutableSet *entities;
+ NSMutableSet *relationshipPaths;
+ NSEnumerator *enumerator;
+ id entityOrRelationship;
+
+ entities = [NSMutableSet set];
+ relationshipPaths = [NSMutableSet set];
+
+ NSAssert3(self->entity,
+ @"entity should be non nil (attrs=%@, qual=%@, order=%@)",
+ attributes, qualifier, fetchOrder);
+
+ for (i = 0, count = [attributes count]; i < count; i++) {
+ EOAttribute *attribute;
+
+ attribute = [attributes objectAtIndex:i];
+
+ if ([attribute entity] != entity) {
+ [[[InvalidAttributeException alloc]
+ initWithFormat:@"all attributes must be from the same "
+ @"entity (attribute '%@' is not in '%@')",
+ [attribute name],
+ [entity name]] raise];
+ }
+ if ([attribute isFlattened]) {
+ id definitionArray = [attribute definitionArray];
+ NSRange range = { 0, [definitionArray count] - 1 };
+ id relationshipPath = [definitionArray subarrayWithRange:range];
+
+ [relationshipPaths addObject:relationshipPath];
+ [entities addObjectsFromArray:relationshipPath];
+ }
+ else {
+ /* attribute is normal. */
+ [entities addObject:[attribute entity]];
+ }
+ }
+
+ [relationshipPaths unionSet:[qualifier relationshipPaths]];
+ [entities unionSet:[qualifier additionalEntities]];
+
+ for (i = 0, count = [fetchOrder count]; i < count; i++) {
+ EOAttribute *attribute;
+ id eorder;
+
+ eorder = [fetchOrder objectAtIndex:i];
+
+ attribute = ([eorder isKindOfClass:[EOSortOrdering class]])
+ ? [self->entity attributeNamed:[(EOSortOrdering *)eorder key]]
+ : [(EOAttributeOrdering *)eorder attribute];
+
+ if ([attribute entity] != entity) {
+ [[[InvalidAttributeException alloc]
+ initWithFormat:@"all attributes must be from the same "
+ @"entity (attribute '%@' is not in '%@')",
+ [attribute name],
+ [entity name]] raise];
+ }
+ if ([attribute isFlattened]) {
+ id definitionArray = [attribute definitionArray];
+ NSRange range = { 0, [definitionArray count] - 1 };
+ id relationshipPath = [definitionArray subarrayWithRange:range];
+
+ [relationshipPaths addObject:relationshipPath];
+ [entities addObjectsFromArray:relationshipPath];
+ }
+ }
+
+ entitiesAndPropertiesAliases = [NSMutableDictionary new];
+ fromListEntities = [NSMutableArray new];
+ enumerator = [entities objectEnumerator];
+ i = 1;
+ while ((entityOrRelationship = [enumerator nextObject])) {
+ NSString* alias = [NSString stringWithFormat:@"t%d", i++];
+
+ [entitiesAndPropertiesAliases setObject:alias
+ forKey:entityOrRelationship];
+ [fromListEntities addObject:entityOrRelationship];
+ }
+
+ return [relationshipPaths allObjects];
+}
+
+- (EOEntity *)entity {
+ return self->entity;
+}
+- (id)finishBuildingExpression {
+ return self;
+}
+- (NSString *)lockClause {
+ return @"";
+}
+
+- (NSString *)expressionValueForAttribute:(EOAttribute *)attribute
+ context:(id)context
+{
+ NSString *alias = [entitiesAndPropertiesAliases objectForKey:context];
+ NSString *columnName = nil;
+
+ columnName = adaptor
+ ? [adaptor formatAttribute:attribute]
+ : [attribute columnName];
+
+ return alias
+ ? [NSString stringWithFormat:@"%@.%@", alias, columnName]
+ : columnName;
+}
+
+- (NSString *)expressionValueForAttribute:(EOAttribute *)attribute {
+ if([attribute isFlattened])
+ return [self expressionValueForAttributePath:
+ [attribute definitionArray]];
+ else if([attribute isDerived])
+ return [[attribute definitionArray] expressionValueForContext:self];
+
+ /* attribute is a normal attribute. Its alias is the alias
+ of its entity. */
+ return [self expressionValueForAttribute:attribute
+ context:[attribute entity]];
+}
+
+- (NSString *)expressionValueForAttributePath:(NSArray *)definitionArray {
+ /* Take the alias of the last relationship. */
+ id relationship;
+ NSString *alias;
+
+ relationship
+ = [definitionArray objectAtIndex:([definitionArray count] - 2)];
+ alias = [entitiesAndPropertiesAliases objectForKey:relationship];
+
+ return AUTORELEASE(([[NSString alloc]
+ initWithFormat:@"%@.%@",
+ alias, [[definitionArray lastObject] columnName]]));
+}
+
+- (NSString *)expressionValueForContext:(id<EOExpressionContext>)context {
+ return self->content;
+}
+
++ (Class)selectExpressionClass {
+ return [EOSelectSQLExpression class];
+}
++ (Class)insertExpressionClass {
+ return [EOInsertSQLExpression class];
+}
++ (Class)deleteExpressionClass {
+ return [EODeleteSQLExpression class];
+}
++ (Class)updateExpressionClass {
+ return [EOUpdateSQLExpression class];
+}
+
+- (EOAdaptor *)adaptor {
+ return self->adaptor;
+}
+
+/* description */
+
+- (NSString *)description {
+ NSMutableString *ms;
+
+ ms = [NSMutableString stringWithCapacity:128];
+ [ms appendFormat:@"<0x%08X[%@]:\n", self, NSStringFromClass([self class])];
+
+ if (self->entity) [ms appendFormat:@" entity=%@\n", self->entity];
+ if (self->adaptor) [ms appendFormat:@" adaptor=%@\n", self->adaptor];
+ if (self->content) [ms appendFormat:@" content='%@\n'", self->content];
+
+ if (self->entitiesAndPropertiesAliases)
+ [ms appendFormat:@" aliases=%@\n", self->entitiesAndPropertiesAliases];
+ if (self->fromListEntities)
+ [ms appendFormat:@" from-entities=%@\n", self->fromListEntities];
+
+ if (self->whereClauseString)
+ [ms appendFormat:@" where=%@\n", self->whereClauseString];
+
+ if (self->listString) [ms appendFormat:@" list=%@\n", self->listString];
+ if (self->bindings) [ms appendFormat:@" bindings=%@\n", self->bindings];
+
+ [ms appendString:@">"];
+ return ms;
+}
+
+@end /* EOSQLExpression */
+
+
+@implementation EOInsertSQLExpression
+@end /* EOInsertSQLExpression */
+
+@implementation EOUpdateSQLExpression
+@end /* EOUpdateSQLExpression */
+
+@implementation EODeleteSQLExpression
+@end /* EODeleteSQLExpression */
+
+@implementation EOSQLExpression(NewInEOF2)
+
++ (EOSQLExpression *)selectStatementForAttributes:(NSArray *)_attributes
+ lock:(BOOL)_flag
+ fetchSpecification:(EOFetchSpecification *)_fspec
+ entity:(EOEntity *)_entity
+{
+ if (_fspec == nil) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"missing fetch specification argument .."];
+ }
+ if ([_attributes count] == 0) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"missing attributes for select .."];
+ }
+
+ return [self selectExpressionForAttributes:_attributes
+ lock:_flag
+ qualifier:[[_fspec qualifier] sqlQualifierForEntity:_entity]
+ fetchOrder:[_fspec sortOrderings]
+ channel:nil];
+}
+
++ (EOSQLExpression *)expressionForString:(NSString *)_sql {
+ EOSQLExpression *se;
+
+ se = [[EOSQLExpression alloc] init];
+ [se setStatement:_sql];
+ return AUTORELEASE(se);
+}
+
+/* accessors */
+
+- (void)setStatement:(NSString *)_stmt {
+ id tmp;
+ tmp = self->content;
+ self->content = [_stmt mutableCopy];
+ RELEASE(tmp);
+}
+- (NSString *)statement {
+ return self->content;
+}
+
+- (NSString *)whereClauseString {
+ return self->whereClauseString;
+}
+
+/* tables */
+
+- (NSString *)tableListWithRootEntity:(EOEntity *)_entity {
+ return ([self->fromListEntities count] > 0)
+ ? [self fromClause]
+ : [_entity externalName];
+}
+
+/* assembly */
+
+- (NSString *)assembleDeleteStatementWithQualifier:(EOQualifier *)_qualifier
+ tableList:(NSString *)_tableList
+ whereClause:(NSString *)_whereClause
+{
+ NSMutableString *s;
+
+ s = [NSMutableString stringWithCapacity:64];
+ [s appendString:@"DELETE FROM "];
+ [s appendString:_tableList];
+ [s appendString:@" WHERE "];
+ [s appendString:_whereClause];
+ return s;
+}
+
+- (NSString *)assembleInsertStatementWithRow:(NSDictionary *)_row
+ tableList:(NSString *)_tables
+ columnList:(NSString *)_columns
+ valueList:(NSString *)_values
+{
+ NSMutableString *s;
+
+ s = [NSMutableString stringWithCapacity:256];
+ [s appendString:@"INSERT INTO "];
+ [s appendString:_tables];
+ [s appendString:@" ("];
+ [s appendString:_columns];
+ [s appendString:@") VALUES ("];
+ [s appendString:_values];
+ [s appendString:@")"];
+ return s;
+}
+
+- (NSString *)assembleSelectStatementWithAttributes:(NSArray *)_attributes
+ lock:(BOOL)_lock
+ qualifier:(EOQualifier *)_qualifier
+ fetchOrder:(NSArray *)_fetchOrder
+ selectString:(NSString *)_selectString
+ columnList:(NSString *)_columns
+ tableList:(NSString *)_tables
+ whereClause:(NSString *)_whereClause
+ joinClause:(NSString *)_joinClause
+ orderByClause:(NSString *)_orderByClause
+ lockClause:(NSString *)_lockClause
+{
+ NSMutableString *s;
+ unsigned wlen, jlen;
+
+#if 0
+#warning DEBUG LOG, REMOVE!
+ [self logWithFormat:@"%s: '%@': %@", __PRETTY_FUNCTION__, _whereClause,self];
+#endif
+
+ s = [NSMutableString stringWithCapacity:256];
+
+ [s appendString:_selectString ? _selectString : @"SELECT"];
+ [s appendString:@" "];
+ [s appendString:_columns];
+ [s appendString:@" FROM "];
+ [s appendString:_tables];
+
+ if ([_lockClause length] > 0) {
+ [s appendString:@" "];
+ [s appendString:_lockClause];
+ }
+
+ wlen = [_whereClause length];
+ jlen = [_joinClause length];
+
+ if ((wlen > 0) || (jlen > 0))
+ [s appendString:@" WHERE "];
+
+ if (wlen > 0)
+ [s appendString:_whereClause];
+
+ if ((wlen > 0) && (jlen > 0))
+ [s appendString:@" AND "];
+
+ if (jlen > 0)
+ [s appendString:_joinClause];
+
+ if ([_orderByClause length] > 0) {
+ [s appendString:@" ORDER BY "];
+ [s appendString:_orderByClause];
+ }
+
+ return s;
+}
+
+- (NSString *)assembleUpdateStatementWithRow:(NSDictionary *)_row
+ qualifier:(EOQualifier *)_qualifier
+ tableList:(NSString *)_tables
+ updateList:(NSString *)_updates
+ whereClause:(NSString *)_whereClause
+{
+ NSMutableString *s;
+
+ s = [NSMutableString stringWithCapacity:256];
+
+ [s appendString:@"UPDATE "];
+ [s appendString:_tables];
+ [s appendString:@" SET "];
+ [s appendString:_updates];
+ [s appendString:@" WHERE "];
+ [s appendString:_whereClause];
+
+ return s;
+}
+
+- (NSString *)assembleJoinClauseWithLeftName:(NSString *)_leftName
+ rightName:(NSString *)_rightName
+ joinSemantic:(EOJoinSemantic)_semantic
+{
+ NSMutableString *s;
+
+ s = [NSMutableString stringWithCapacity:64];
+ [s appendString:_leftName];
+ switch (_semantic) {
+ case EOInnerJoin:
+ [s appendString:@" = "];
+ break;
+ case EOFullOuterJoin:
+ [s appendString:@" *=* "];
+ break;
+ case EOLeftOuterJoin:
+ [s appendString:@" *= "];
+ break;
+ case EORightOuterJoin:
+ [s appendString:@" =* "];
+ break;
+ }
+ [s appendString:_rightName];
+ return s;
+}
+
+/* attributes */
+
+- (NSString *)sqlStringForAttribute:(EOAttribute *)_attribute {
+ NSLog(@"ERROR(%s): subclasses need to override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+- (NSString *)sqlStringForAttributePath:(NSString *)_attrPath {
+ NSLog(@"ERROR(%s): subclasses need to override this method!",
+ __PRETTY_FUNCTION__);
+ return nil;
+}
+
+- (NSString *)sqlStringForAttributeNamed:(NSString *)_attrName {
+ EOAttribute *a;
+
+ if ((a = [[self entity] attributeNamed:_attrName]))
+ return [self sqlStringForAttribute:a];
+
+ return [self sqlStringForAttributePath:_attrName];
+}
+
+/* bind variables */
+
++ (BOOL)useBindVariables {
+ return NO;
+}
+- (BOOL)mustUseBindVariableForAttribute:(EOAttribute *)_attr {
+ return NO;
+}
+- (BOOL)shouldUseBindVariableForAttribute:(EOAttribute *)_attr {
+ return NO;
+}
+
+- (NSMutableDictionary *)bindVariableDictionaryForAttribute:(EOAttribute *)_attr
+ value:(id)_value
+{
+ NSMutableDictionary *d;
+
+ d = [NSMutableDictionary dictionaryWithCapacity:8];
+ [d setObject:_attr forKey:EOBindVariableAttributeKey];
+ [d setObject:_value ? _value : null forKey:EOBindVariableValueKey];
+ return d;
+}
+
+- (void)addBindVariableDictionary:(NSMutableDictionary *)_dictionary {
+ if (self->bindings == nil)
+ self->bindings = [[NSMutableArray alloc] init];
+}
+- (NSArray *)bindVariableDictionaries {
+ return self->bindings;
+}
+
+/* values */
+
++ (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute {
+ return _value ? _value : null;
+}
+
+- (NSString *)sqlStringForValue:(id)_value attributeNamed:(NSString *)_attrName {
+ NSMutableDictionary *bindVars;
+ EOAttribute *attribute;
+
+ attribute = [[self entity] attributeNamed:_attrName];
+
+ if ([self mustUseBindVariableForAttribute:attribute])
+ bindVars = [self bindVariableDictionaryForAttribute:attribute value:_value];
+ else if ([[self class] useBindVariables] &&
+ [self shouldUseBindVariableForAttribute:attribute]) {
+ bindVars = [self bindVariableDictionaryForAttribute:attribute value:_value];
+ }
+ else
+ bindVars = nil;
+
+ if (bindVars) {
+ [self addBindVariableDictionary:bindVars];
+ return [bindVars objectForKey:EOBindVariablePlaceHolderKey];
+ }
+
+ return [[self class] formatValue:_value?_value:null forAttribute:attribute];
+}
+
++ (NSString *)sqlPatternFromShellPattern:(NSString *)_pattern {
+ unsigned len;
+
+ if ((len = [_pattern length]) > 0) {
+ unsigned cstrLen = [_pattern cStringLength];
+ char cstrBuf[cstrLen + 1];
+ const char *cstr;
+ char buf[len * 3 + 1];
+ unsigned i;
+ BOOL didSomething = NO;
+
+ [_pattern getCString:cstrBuf];
+ cstr = cstrBuf;
+
+ for (i = 0; *cstr; cstr++) {
+ switch (*cstr) {
+ case '*':
+ buf[i] = '%'; i++; didSomething = YES;
+ break;
+ case '?':
+ buf[i] = '_'; i++; didSomething = YES;
+ break;
+
+ case '%':
+ buf[i] = '['; i++;
+ buf[i] = '%'; i++;
+ buf[i] = ']'; i++;
+ didSomething = YES;
+ break;
+
+ case '_':
+ buf[i] = '['; i++;
+ buf[i] = '_'; i++;
+ buf[i] = ']'; i++;
+ didSomething = YES;
+ break;
+
+ default:
+ buf[i] = *cstr;
+ i++;
+ break;
+ }
+ }
+ buf[i] = '\0';
+
+ return (didSomething)
+ ? [NSString stringWithCString:buf length:i]
+ : _pattern;
+ }
+ return _pattern;
+}
+
+/* SQL formats */
+
++ (NSString *)formatSQLString:(NSString *)_sqlString format:(NSString *)_fmt {
+ return _sqlString;
+}
+
+/* qualifier operators */
+
+- (NSString *)sqlStringForSelector:(SEL)_selector value:(id)_value {
+ if ((_value == null) || (_value == nil)) {
+ if (sel_eq(_selector, EOQualifierOperatorEqual))
+ return @"is";
+ else if (sel_eq(_selector, EOQualifierOperatorNotEqual))
+ return @"is not";
+ }
+ else {
+ if (sel_eq(_selector, EOQualifierOperatorEqual))
+ return @"=";
+ else if (sel_eq(_selector, EOQualifierOperatorNotEqual))
+ return @"<>";
+ }
+
+ if (sel_eq(_selector, EOQualifierOperatorLessThan))
+ return @"<";
+ else if (sel_eq(_selector, EOQualifierOperatorGreaterThan))
+ return @">";
+ else if (sel_eq(_selector, EOQualifierOperatorLessThanOrEqualTo))
+ return @"<=";
+ else if (sel_eq(_selector, EOQualifierOperatorGreaterThanOrEqualTo))
+ return @">=";
+ else if (sel_eq(_selector, EOQualifierOperatorLike))
+ return @"LIKE";
+ else {
+ return [NSString stringWithFormat:@"UNKNOWN<%@>",
+ NSStringFromSelector(_selector)];
+ }
+}
+
+/* qualifiers */
+
+- (NSString *)sqlStringForKeyComparisonQualifier:(EOKeyComparisonQualifier *)_q {
+ NSMutableString *s;
+ NSString *sql;
+ EOAttribute *a;
+
+ s = [NSMutableString stringWithCapacity:64];
+
+ sql = [self sqlStringForAttributeNamed:[_q leftKey]];
+ a = [[self entity] attributeNamed:[_q leftKey]]; /* relationships ? */
+ sql = [[self class] formatSQLString:sql format:[a readFormat]];
+ [s appendString:sql];
+
+ [s appendString:@" "];
+ [s appendString:[self sqlStringForSelector:[_q selector] value:nil]];
+ [s appendString:@" "];
+
+ sql = [self sqlStringForAttributeNamed:[_q rightKey]];
+ a = [[self entity] attributeNamed:[_q rightKey]]; /* relationships ? */
+ sql = [[self class] formatSQLString:sql format:[a readFormat]];
+ [s appendString:sql];
+
+ return s;
+}
+
+- (NSString *)sqlStringForKeyValueQualifier:(EOKeyValueQualifier *)_q {
+ NSMutableString *s;
+ NSString *sql;
+ EOAttribute *a;
+ id v;
+
+ v = [_q value];
+ s = [NSMutableString stringWithCapacity:64];
+
+ sql = [self sqlStringForAttributeNamed:[_q key]];
+ a = [[self entity] attributeNamed:[_q key]]; /* relationships ? */
+ sql = [[self class] formatSQLString:sql format:[a readFormat]];
+ [s appendString:sql];
+
+ [s appendString:@" "];
+ sql = [self sqlStringForSelector:[_q selector] value:v];
+ [s appendString:sql];
+ [s appendString:@" "];
+
+ if (([_q selector] == EOQualifierOperatorLike) ||
+ ([_q selector] == EOQualifierOperatorCaseInsensitiveLike))
+ v = [[self class] sqlPatternFromShellPattern:v];
+
+ sql = [self sqlStringForValue:v attributeNamed:[_q key]];
+ [s appendString:sql];
+ return s;
+}
+
+- (NSString *)sqlStringForNegatedQualifier:(EOQualifier *)_q {
+ NSMutableString *s;
+ NSString *sql;
+
+ sql = [(id<EOQualifierSQLGeneration>)_q sqlStringForSQLExpression:self];
+ s = [NSMutableString stringWithCapacity:[sql length] + 8];
+ [s appendString:@"NOT ("];
+ [s appendString:sql];
+ [s appendString:@")"];
+ return s;
+}
+
+- (NSString *)sqlStringForConjoinedQualifiers:(NSArray *)_qs {
+ NSMutableString *s;
+ unsigned i, count;
+ id (*objAtIdx)(id,SEL,unsigned);
+
+ objAtIdx = (void *)[_qs methodForSelector:@selector(objectAtIndex:)];
+ for (i = 0, count = [_qs count], s = nil; i < count; i++) {
+ id<EOQualifierSQLGeneration> q;
+
+ q = objAtIdx(self, @selector(objectAtIndex:), i);
+
+ if (s == nil)
+ s = [NSMutableString stringWithCapacity:128];
+ else
+ [s appendString:@" AND "];
+
+ [s appendString:[q sqlStringForSQLExpression:self]];
+ }
+ return s;
+}
+
+- (NSString *)sqlStringForDisjoinedQualifiers:(NSArray *)_qs {
+ NSMutableString *s;
+ unsigned i, count;
+ id (*objAtIdx)(id,SEL,unsigned);
+
+ objAtIdx = (void *)[_qs methodForSelector:@selector(objectAtIndex:)];
+ for (i = 0, count = [_qs count], s = nil; i < count; i++) {
+ id<EOQualifierSQLGeneration> q;
+
+ q = objAtIdx(self, @selector(objectAtIndex:), i);
+
+ if (s == nil)
+ s = [NSMutableString stringWithCapacity:128];
+ else
+ [s appendString:@" OR "];
+
+ [s appendString:[q sqlStringForSQLExpression:self]];
+ }
+ return s;
+}
+
+/* list strings */
+
+- (NSMutableString *)listString {
+ if (self->listString == nil)
+ self->listString = [[NSMutableString alloc] initWithCapacity:128];
+ return self->listString;
+}
+
+- (void)appendItem:(NSString *)_itemString toListString:(NSMutableString *)_ls {
+ if ([_ls length] > 0)
+ [_ls appendString:@","];
+ [_ls appendString:_itemString];
+}
+
+/* deletes */
+
+- (void)prepareDeleteExpressionForQualifier:(EOQualifier *)_qual {
+ NSString *tableList, *sql;
+
+ self->whereClauseString =
+ [[(id<EOQualifierSQLGeneration>)_qual sqlStringForSQLExpression:self] copy];
+
+ tableList = [self tableListWithRootEntity:[self entity]];
+
+ sql = [self assembleDeleteStatementWithQualifier:_qual
+ tableList:tableList
+ whereClause:[self whereClauseString]];
+
+ [self setStatement:sql];
+}
+
+/* updates */
+
+- (void)addUpdateListAttribute:(EOAttribute *)_attr value:(NSString *)_value {
+ NSMutableString *s;
+
+ s = [[NSMutableString alloc] initWithCapacity:32];
+ [s appendString:[_attr columnName]];
+ [s appendString:@"="];
+ _value = [[self class] formatSQLString:_value format:[_attr writeFormat]];
+ [s appendString:_value];
+
+ [self appendItem:s toListString:[self listString]];
+ RELEASE(s);
+}
+
+- (void)prepareUpdateExpressionWithRow:(NSDictionary *)_row
+ qualifier:(EOQualifier *)_qual
+{
+ NSEnumerator *keys;
+ NSString *key;
+ NSString *tableList, *sql;
+
+ keys = [_row keyEnumerator];
+ while ((key = [keys nextObject])) {
+ EOAttribute *attribute;
+ id value;
+
+ attribute = [self->entity attributeNamed:key];
+ value = [_row objectForKey:key];
+
+ [self addUpdateListAttribute:attribute value:value];
+ }
+
+ self->whereClauseString =
+ [[(id<EOQualifierSQLGeneration>)_qual sqlStringForSQLExpression:self] copy];
+
+ tableList = [self tableListWithRootEntity:[self entity]];
+
+ sql = [self assembleUpdateStatementWithRow:_row
+ qualifier:_qual
+ tableList:tableList
+ updateList:[self listString]
+ whereClause:[self whereClauseString]];
+
+ [self setStatement:sql];
+}
+
+@end /* EOSQLExpression(NewInEOF2) */
--- /dev/null
+/*
+ EOSQLQualifier.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@apache.org>
+ Helge Hess <helge.hess@opengroupware.org>
+ Date: September 1996
+ November 1999
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#import "common.h"
+#import "EOSQLQualifier.h"
+#import "EOAdaptor.h"
+#import "EOAttribute.h"
+#import "EOEntity.h"
+#import "EOExpressionArray.h"
+#import "EOFExceptions.h"
+#import "EORelationship.h"
+#import "EOSQLExpression.h"
+#include <EOControl/EOKeyValueCoding.h>
+#include <EOControl/EONull.h>
+#import "EOQualifierScanner.h"
+
+#if LIB_FOUNDATION_LIBRARY
+# include <extensions/DefaultScannerHandler.h>
+# include <extensions/PrintfFormatScanner.h>
+#else
+# include "DefaultScannerHandler.h"
+# include "PrintfFormatScanner.h"
+#endif
+
+@interface EOQualifierJoinHolder : NSObject
+{
+ id source;
+ id destination;
+}
++ (id)valueForSource:(id)source destination:(id)destination;
+- (NSString*)expressionValueForContext:(EOSQLExpression*)context;
+- (id)source;
+- (id)destination;
+@end
+
+@implementation EOQualifierJoinHolder
+
+static Class AttributeClass = Nil;
+static EONull *null = nil;
+
++ (void)initialize {
+ AttributeClass = [EOAttribute class];
+ null = [[NSNull null] retain];
+}
+
++ (id)valueForSource:(id)_source destination:(id)_destination {
+ EOQualifierJoinHolder *value;
+
+ value = [[[self alloc] init] autorelease];
+ value->source = [_source retain];
+ value->destination = [_destination retain];
+ return value;
+}
+
+- (NSString *)expressionValueForContext:(EOSQLExpression *)context {
+ NSMutableString *result = nil;
+ EOAdaptor *adaptor = nil;
+ NSString *formattedLeft = nil;
+ NSString *formattedRight = nil;
+ BOOL checkNull = NO;
+
+ adaptor = [context adaptor];
+
+ if ([source isKindOfClass:AttributeClass]) {
+ formattedLeft = [source expressionValueForContext:context];
+ }
+ else {
+ NSAssert([destination isKindOfClass:AttributeClass],
+ @"either one of source or destination should be EOAttribute");
+ if ([source isEqual:null] || (source == nil))
+ checkNull = YES;
+
+ formattedLeft = [adaptor formatValue:source?source:null
+ forAttribute:destination];
+ }
+
+ if ([destination isKindOfClass:AttributeClass]) {
+ NSString *tmp = formattedLeft;
+
+ formattedLeft = [destination expressionValueForContext:context];
+ formattedRight = tmp;
+ }
+ else {
+ NSAssert([source isKindOfClass:AttributeClass],
+ @"either one of source or destination should be EOAttribute");
+
+ if ([destination isEqual:null] || (destination == nil))
+ checkNull = YES;
+
+ formattedRight = [adaptor formatValue:destination?destination:null
+ forAttribute:source];
+ }
+
+ result = [NSMutableString stringWithCapacity:64];
+ [result appendString:formattedLeft];
+ [result appendString:checkNull ? @" IS " : @"="];
+ [result appendString:formattedRight];
+ return result;
+}
+
+- (id)source {
+ return self->source;
+}
+- (id)destination {
+ return self->destination;
+}
+
+@end /* EOQualifierJoinHolder */
+
+
+@implementation EOSQLQualifier
+
++ (EOSQLQualifier*)qualifierForRow:(NSDictionary*)row
+ entity:(EOEntity*)_entity
+{
+ EOSQLQualifier *qualifier = nil;
+ NSEnumerator *enumerator = nil;
+ NSString *attributeName = nil;
+ EOAttribute *attribute = nil;
+ id value = nil;
+ BOOL first = YES;
+
+ enumerator = [row keyEnumerator];
+ qualifier = [[[EOSQLQualifier alloc] init] autorelease];
+
+ while ((attributeName = [enumerator nextObject])) {
+ attribute = [_entity attributeNamed:attributeName];
+ value = [row objectForKey:attributeName];
+
+ if ((value == nil) || (attribute == nil))
+ /* return nil when is unable to build a qualifier for all keys
+ in the given row
+ */
+ return nil;
+
+ if (first)
+ first = NO;
+ else
+ [qualifier->content addObject:@" AND "];
+
+ [qualifier->content addObject:
+ [EOQualifierJoinHolder valueForSource:attribute destination:value]];
+ }
+
+ qualifier->entity = RETAIN(_entity);
+ [qualifier _computeRelationshipPaths];
+
+ return qualifier;
+}
+
++ (EOSQLQualifier*)qualifierForPrimaryKey:(NSDictionary*)dictionary
+ entity:(EOEntity*)_entity
+{
+ NSDictionary *pkey = nil;
+
+ pkey = [_entity primaryKeyForRow:dictionary];
+ /* return nil when is unable to build a complete qualifier
+ for all primary key attributes
+ */
+ return pkey ? [self qualifierForRow:pkey entity:_entity] : nil;
+}
+
++ (EOSQLQualifier*)qualifierForRow:(NSDictionary*)row
+ relationship:(EORelationship*)relationship
+{
+ NSArray *componentRelationships = nil;
+ EOSQLQualifier *qualifier = nil;
+ NSArray *sourceAttributes = nil;
+ id tmpRelationship = nil;
+ EOAttribute *sourceAttribute = nil;
+ EOAttribute *destinationAttribute = nil;
+ id value = nil;
+ int j = 0;
+ int count2 = 0;
+
+ componentRelationships = [relationship componentRelationships];
+ tmpRelationship = relationship;
+ qualifier = [[[EOSQLQualifier alloc] init] autorelease];
+
+ /* Make a qualifier string in the following manner. If the relationship is
+ not flattened we must join using the join operator the values from `row'
+ and the foreign keys taken from the destination entity of relatioship.
+ If the relationship is flattend we must append then joins between the
+ components of relationship. */
+
+ if (componentRelationships) {
+ tmpRelationship = [componentRelationships objectAtIndex:0];
+
+ sourceAttributes =
+ [NSArray arrayWithObject:[tmpRelationship sourceAttribute]];
+ }
+ else {
+ sourceAttributes =
+ [NSArray arrayWithObject:[relationship sourceAttribute]];
+ }
+
+ sourceAttribute = [tmpRelationship sourceAttribute];
+ value = [row objectForKey:[sourceAttribute name]];
+ if (value == nil)
+ /* Returns nil if `row' does not contain all the values needed to
+ create a complete qualifier
+ */
+ return nil;
+
+ destinationAttribute = [tmpRelationship destinationAttribute];
+ [qualifier->content addObject:
+ [EOQualifierJoinHolder valueForSource:destinationAttribute
+ destination:value]];
+
+ if (componentRelationships) {
+ EOEntity *tempEntity = [tmpRelationship destinationEntity];
+
+ /* The relationship is flattened. Iterate over the components and
+ add joins that `link' the components between them.
+ */
+ count2 = [componentRelationships count];
+ for (j = 1; j < count2; j++) {
+ relationship = [componentRelationships objectAtIndex:j];
+
+ if ([relationship sourceAttribute]) {
+ [qualifier->content addObject:@" AND "];
+ [qualifier->content addObject:
+ [EOQualifierJoinHolder valueForSource:
+ [relationship sourceAttribute]
+ destination:
+ [relationship destinationAttribute]]];
+ }
+ }
+
+ /* Here we make a hack because later we need to use this qualifier in
+ a SELECT expression in which the qualifier's entity should be the
+ final destination entity of the flattened relationship. In addition
+ we need in the FROM clause all the entities corresponding to the
+ components of the relationship to be able to insert the joins
+ between the values given in row and the final attributes from the
+ destination entity of the last component of relationship. */
+ ASSIGN(qualifier->entity, tempEntity);
+ [qualifier _computeRelationshipPaths];
+ ASSIGN(qualifier->entity, [relationship destinationEntity]);
+ return qualifier;
+ }
+ else {
+ ASSIGN(qualifier->entity, [relationship destinationEntity]);
+ return qualifier;
+ }
+}
+
++ (EOSQLQualifier *)qualifierForObject:sourceObject
+ relationship:(EORelationship *)relationship
+{
+ return [self qualifierForRow:
+ [sourceObject valueForKey:[[relationship sourceAttribute] name]]
+ relationship:relationship];
+}
+
+- (id)init {
+ NSZone *z = [self zone];
+
+ RELEASE(self->content); self->content = nil;
+ RELEASE(self->relationshipPaths); self->relationshipPaths = nil;
+ RELEASE(self->additionalEntities); self->additionalEntities = nil;
+
+ self->content = [[EOExpressionArray allocWithZone:z] init];
+ self->relationshipPaths = [[NSMutableSet allocWithZone:z] init];
+ self->additionalEntities = [[NSMutableSet allocWithZone:z] init];
+ return self;
+}
+
+- (id)initWithEntity:(EOEntity *)_entity
+ qualifierFormat:(NSString *)_qualifierFormat
+ argumentsArray:(NSArray *)_args
+{
+ PrintfFormatScanner *formatScanner = nil;
+ EOQualifierEnumScannerHandler *scannerHandler = nil;
+ NSString *qualifierString = nil;
+ NSMutableArray *myRelationshipPaths = nil;
+ NSEnumerator *args = nil;
+
+ myRelationshipPaths = [[NSMutableArray allocWithZone:[self zone]] init];
+
+ [self init];
+ ASSIGN(self->entity, _entity);
+
+ if (_qualifierFormat == nil)
+ return self;
+
+ formatScanner = [[PrintfFormatScanner alloc] init];
+ scannerHandler = [[EOQualifierEnumScannerHandler alloc] init];
+ [formatScanner setAllowOnlySpecifier:YES];
+
+ args = [_args objectEnumerator];
+ [scannerHandler setEntity:_entity];
+
+ [formatScanner setFormatScannerHandler:scannerHandler];
+ /*
+ Note: This is an ugly hack. Arguments is supposed to be a va_args
+ structure, but an NSArray is passed in.
+ It works because the value is casted to -parseFormatString:context:
+ which gives control to the scannerHandler which casts the va_args
+ back to an array (the EOQualifierEnumScannerHandler does that).
+ Works on ix86, but *NOT* on iSeries or zServer !!
+ */
+#if defined(__s390__)
+ qualifierString =
+ [formatScanner performSelector:@selector(stringWithFormat:arguments:)
+ withObject:_qualifierFormat
+ withObject:args];
+#else
+ qualifierString =
+ [formatScanner stringWithFormat:_qualifierFormat
+ arguments:args];
+#endif
+
+ [formatScanner release]; formatScanner = nil;
+ [scannerHandler release]; scannerHandler = nil;
+
+ [self->content release]; self->content = nil;
+ self->content =
+ [[EOExpressionArray parseExpression:qualifierString
+ entity:entity
+ replacePropertyReferences:YES
+ relationshipPaths:myRelationshipPaths]
+ retain];
+ [self _computeRelationshipPaths:myRelationshipPaths];
+ [myRelationshipPaths release]; myRelationshipPaths = nil;
+ return self;
+}
+
+- (id)initWithEntity:(EOEntity*)_entity
+ qualifierFormat:(NSString *)qualifierFormat, ...
+{
+ va_list ap;
+ id formatScanner = nil;
+ id scannerHandler = nil;
+ NSString *qualifierString = nil;
+ NSMutableArray *myRelationshipPaths = nil;
+
+ if ((self = [self init]) == nil)
+ return nil;
+
+ myRelationshipPaths = [[NSMutableArray alloc] init];
+ ASSIGN(self->entity, _entity);
+
+ if (qualifierFormat == nil) {
+ return self;
+ }
+
+ formatScanner = [[PrintfFormatScanner alloc] init];
+ scannerHandler = [[EOQualifierScannerHandler alloc] init];
+ [formatScanner setAllowOnlySpecifier:YES];
+
+ va_start(ap, qualifierFormat);
+ [scannerHandler setEntity:_entity];
+ [formatScanner setFormatScannerHandler:scannerHandler];
+ qualifierString = [formatScanner stringWithFormat:qualifierFormat
+ arguments:ap];
+ va_end(ap);
+
+ [formatScanner release];
+ [scannerHandler release];
+
+ [self->content release]; self->content = nil;
+ self->content =
+ [[EOExpressionArray parseExpression:qualifierString
+ entity:entity
+ replacePropertyReferences:YES
+ relationshipPaths:myRelationshipPaths] retain];
+ [self _computeRelationshipPaths:myRelationshipPaths];
+ [myRelationshipPaths release]; myRelationshipPaths = nil;
+ return self;
+}
+
+- (void)_computeRelationshipPaths {
+ [self _computeRelationshipPaths:nil];
+}
+
+static void
+handle_attribute(EOSQLQualifier *self, id object, id _relationshipPaths)
+{
+ if ([object isFlattened]) {
+ id definitionArray = nil;
+ id relsArray = nil;
+ NSRange range;
+
+ definitionArray = [object definitionArray];
+ range = NSMakeRange(0, [definitionArray count] - 1);
+ relsArray = [definitionArray subarrayWithRange:range];
+
+ [self->relationshipPaths addObject:relsArray];
+ [self->additionalEntities addObjectsFromArray:relsArray];
+ }
+ else {
+ [self->additionalEntities addObject:[object entity]];
+ }
+}
+
+- (void)_computeRelationshipPaths:(NSArray *)_relationshipPaths {
+ int i, count;
+
+ [relationshipPaths removeAllObjects];
+
+ if (_relationshipPaths) {
+ NSEnumerator *pathEnum = [_relationshipPaths objectEnumerator];
+ NSArray *relPath = nil;
+
+ while ((relPath = [pathEnum nextObject])) {
+ NSEnumerator *relEnum = nil;
+ EORelationship *rel = nil;
+
+ relEnum = [relPath objectEnumerator];
+
+ while ((rel = [relEnum nextObject])) {
+ [additionalEntities addObject:[rel destinationEntity]];
+ }
+ }
+ [relationshipPaths addObjectsFromArray:_relationshipPaths];
+ }
+ for (i = 0, count = [content count]; i < count; i++) {
+ id object = [content objectAtIndex:i];
+
+ /* The objects from content can only be NSString, values or
+ EOAttribute. */
+ if ([object isKindOfClass:[EOAttribute class]]) {
+ handle_attribute (self, object, _relationshipPaths);
+ }
+ else if ([object isKindOfClass:[EOQualifierJoinHolder class]]) {
+ id source = nil;
+ id destination = nil;
+
+ source = [object source];
+ destination = [object destination];
+
+ if ([source isKindOfClass:[EOAttribute class]])
+ handle_attribute (self, source, _relationshipPaths);
+ if ([destination isKindOfClass:[EOAttribute class]])
+ handle_attribute (self, destination, _relationshipPaths);
+ }
+ else if ([object isKindOfClass:[EORelationship class]]) {
+ [[[InvalidPropertyException alloc]
+ initWithFormat:@"cannot refer a EORelat"
+ @"ionship in a EOSQLQualifier: '%@'",
+ [(EORelationship*)object name]] raise];
+ }
+ }
+}
+
+- (void)dealloc {
+ RELEASE(self->relationshipPaths);
+ RELEASE(self->additionalEntities);
+
+ RELEASE(self->entity);
+ RELEASE(self->content);
+ [super dealloc];
+}
+
+- (id)copy {
+ return [self copyWithZone:NSDefaultMallocZone()];
+}
+
+- (id)copyWithZone:(NSZone*)zone {
+ EOSQLQualifier* copy = nil;
+
+ copy = [[self->isa allocWithZone:zone] init];
+ copy->entity = RETAIN(self->entity);
+ copy->content = [self->content mutableCopyWithZone:zone];
+ copy->relationshipPaths = [self->relationshipPaths mutableCopyWithZone:zone];
+ copy->usesDistinct = self->usesDistinct;
+ return copy;
+}
+
+- (void)negate {
+ [self->content insertObject:@"NOT (" atIndex:0];
+ [self->content addObject:@")"];
+}
+
+- (void)conjoinWithQualifier:(EOSQLQualifier*)qualifier {
+ if (![qualifier isKindOfClass:[EOSQLQualifier class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"argument of conjoinWithQualifier: method must "
+ @"be EOSQLQualifier"];
+ }
+
+ if (self->entity != qualifier->entity) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"qualifier argument of conjoinWithQualifier: "
+ @"must have the same entity as receiver"];
+ }
+
+ [self->content insertObject:@"(" atIndex:0];
+ [self->content addObject:@") AND ("];
+ [self->content addObjectsFromExpressionArray:qualifier->content];
+ [self->content addObject:@")"];
+ [self->relationshipPaths unionSet:qualifier->relationshipPaths];
+}
+
+- (void)disjoinWithQualifier:(EOSQLQualifier*)qualifier {
+ if (![qualifier isKindOfClass:[EOSQLQualifier class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"argument of disjoinWithQualifier: method must "
+ @"be EOSQLQualifier"];
+ }
+
+ if (self->entity != qualifier->entity) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"qualifier argument of disjoinWithQualifier: "
+ @"must have the same entity as receiver"];
+ }
+
+ [self->content insertObject:@"(" atIndex:0];
+ [self->content addObject:@") OR ("];
+ [self->content addObjectsFromExpressionArray:qualifier->content];
+ [self->content addObject:@")"];
+ [self->relationshipPaths unionSet:qualifier->relationshipPaths];
+}
+
+- (EOEntity*)entity {
+ return self->entity;
+}
+- (BOOL)isEmpty {
+ return (self->entity == nil) ? YES : NO;
+}
+- (void)setUsesDistinct:(BOOL)flag {
+ self->usesDistinct = flag;
+}
+- (BOOL)usesDistinct {
+ return self->usesDistinct;
+}
+- (NSMutableSet*)relationshipPaths {
+ return self->relationshipPaths;
+}
+- (NSMutableSet*)additionalEntities {
+ return self->additionalEntities;
+}
+
+- (NSString*)expressionValueForContext:(id<EOExpressionContext>)ctx {
+ return [self->content expressionValueForContext:ctx];
+}
+
+- (EOSQLQualifier *)sqlQualifierForEntity:(EOEntity *)_entity {
+ NSAssert3(self->entity == _entity,
+ @"passed invalid entity to %@ (contains %@, got %@)",
+ self, self->entity, _entity);
+ return (EOSQLQualifier *)self;
+}
+
+/* description */
+
+- (NSString *)description {
+ NSMutableString *ms;
+
+ ms = [NSMutableString stringWithCapacity:128];
+ [ms appendFormat:@"<0x%08X[%@]:\n", self, NSStringFromClass([self class])];
+
+ [ms appendFormat:@" entity=%@", [self->entity name]];
+
+ if (self->content)
+ [ms appendFormat:@" content=%@", self->content];
+
+ if (self->usesDistinct)
+ [ms appendString:@" distinct"];
+
+ [ms appendString:@">"];
+ return ms;
+}
+
+@end /* EOSQLQualifier */
--- /dev/null
+/*
+ EOSQLExpression.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: September 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "EOSQLExpression.h"
+#include "EOAttribute.h"
+#include "EOAdaptor.h"
+#include "common.h"
+
+#if LIB_FOUNDATION_LIBRARY
+# include <extensions/DefaultScannerHandler.h>
+# include <extensions/PrintfFormatScanner.h>
+#else
+# include "DefaultScannerHandler.h"
+# include "PrintfFormatScanner.h"
+#endif
+
+@interface EOSelectScannerHandler : DefaultScannerHandler
+{
+ EOAttribute *attribute;
+ EOAdaptor *adaptor;
+ NSString *alias;
+}
+
+- (void)setAttribute:(EOAttribute*)attribute
+ adaptor:(EOAdaptor*)adaptor
+ alias:(NSString*)alias;
+
+@end
+
+@implementation EOSelectSQLExpression
+
+- (NSString *)expressionValueForAttribute:(EOAttribute *)attribute
+ context:(id)context
+{
+ NSString *alias;
+ NSString *columnName;
+ NSString *selectFormat;
+
+ alias = [entitiesAndPropertiesAliases objectForKey:context];
+ selectFormat = [attribute selectFormat];
+
+ //NSLog(@"entitiesAndPropertiesAliases: %@", entitiesAndPropertiesAliases);
+
+ if (selectFormat) {
+ PrintfFormatScanner *formatScanner;
+ EOSelectScannerHandler *scannerHandler;
+
+ formatScanner =
+ [[[[PrintfFormatScanner alloc] init] setAllowOnlySpecifier:YES]
+ autorelease];
+ scannerHandler =
+ [[[EOSelectScannerHandler alloc] init] autorelease];
+
+ [scannerHandler setAttribute:attribute adaptor:adaptor alias:alias];
+ [formatScanner setFormatScannerHandler:scannerHandler];
+#if defined(__s390__)
+ return [formatScanner performSelector:
+ @selector(stringWithFormat:arguments:)
+ withObject:selectFormat
+ withObject:nil];
+#else
+ return [formatScanner stringWithFormat:selectFormat arguments:NULL];
+#endif
+ }
+ else {
+ columnName = adaptor
+ ? [adaptor formatAttribute:attribute]
+ : [attribute columnName];
+
+ if (alias) {
+ return [([[NSString alloc] initWithFormat:@"%@.%@",
+ alias, columnName]) autorelease];
+ }
+
+ return columnName;
+ }
+}
+
+@end /* EOSelectSQLExpression */
+
+@implementation EOSelectScannerHandler
+
+- (id)init
+{
+ [super init];
+
+ specHandler['A']
+ = [self methodForSelector:@selector(convertAttribute:scanner:)];
+ return self;
+}
+
+- (void)dealloc
+{
+ RELEASE(self->attribute);
+ RELEASE(self->adaptor);
+ RELEASE(self->alias);
+ [super dealloc];
+}
+
+- (void)setAttribute:(EOAttribute*)_attribute
+ adaptor:(EOAdaptor*)_adaptor
+ alias:(NSString*)_alias
+{
+ ASSIGN(self->attribute, _attribute);
+ ASSIGN(self->adaptor, _adaptor);
+ ASSIGN(self->alias, _alias);
+}
+
+- (NSString *)convertAttribute:(va_list *)pString
+ scanner:(FormatScanner *)scanner
+{
+ NSString *columnName;
+
+ columnName = (adaptor)
+ ? [adaptor formatAttribute:self->attribute]
+ : [self->attribute columnName];
+
+ if (alias)
+ return [NSString stringWithFormat:@"%@.%@", alias, columnName];
+
+ return columnName;
+}
+
+@end /* EOSelectScannerHandler */
--- /dev/null
+
+Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for ANY purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation. This software may be included in any commercial product
+provided that its distribution contain the libFoundation copyright notice
+and this permission notice.
+
+We disclaim all warranties with regard to this software, including all
+implied warranties of merchantability and fitness, in no event shall
+we be liable for any special, indirect or consequential damages or any
+damages whatsoever resulting from loss of use, data or profits, whether in
+an action of contract, negligence or other tortious action, arising out of
+or in connection with the use or performance of this software.
--- /dev/null
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@apache.org>
+ Helge Hess <helge.hess@opengroupware.org>
--- /dev/null
+/*
+ DefaultScannerHandler.h
+
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+ This file is part of libFoundation.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
+*/
+
+#ifndef __DefaultScannerHandler_h__
+#define __DefaultScannerHandler_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+@class FormatScanner;
+
+@interface DefaultScannerHandler : NSObject
+{
+ IMP specHandler[256];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:(id)aFormatScanner;
+- (NSString *)unknownSpecifier:(void *)arg scanner:(id)scanner;
+
+@end
+
+@class NSEnumerator;
+
+@interface DefaultEnumScannerHandler : NSObject
+{
+ IMP specHandler[256];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:(id)aFormatScanner;
+- (NSString *)unknownSpecifier:(void *)arg scanner:(id)scanner;
+
+@end
+
+#endif /* __DefaultScannerHandler_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ DefaultScannerHandler.m
+
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@apache.org>
+ Helge Hess <helge.hess@opengroupware.org>
+
+ This file is part of libFoundation.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
+*/
+
+#import <Foundation/NSString.h>
+#include "FormatScanner.h"
+#include "DefaultScannerHandler.h"
+
+@implementation DefaultScannerHandler
+
+- (id)init {
+ int i;
+ IMP unknownSpecifierIMP
+ = [self methodForSelector:@selector(unknownSpecifier:scanner:)];
+
+ for(i = 0; i < 256; i++)
+ specHandler[i] = unknownSpecifierIMP;
+ return self;
+}
+
+- (NSString *)unknownSpecifier:(void *)arg scanner:scanner
+{
+ char str[] = { [scanner characterSpecifier], 0 };
+ return [NSString stringWithCString:str];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:scanner
+{
+ return (*specHandler[(int)[scanner characterSpecifier]])
+ (self, _cmd, arg, scanner);
+}
+
+@end /* DefaultScannerHandler */
+
+@implementation DefaultEnumScannerHandler
+
+- (id)init
+{
+ int i;
+ IMP unknownSpecifierIMP;
+
+ unknownSpecifierIMP =
+ [self methodForSelector:@selector(unknownSpecifier:scanner:)];
+
+ for(i = 0; i < 256; i++)
+ self->specHandler[i] = unknownSpecifierIMP;
+ return self;
+}
+
+- (NSString *)unknownSpecifier:(void *)arg scanner:scanner
+{
+ char str[] = { [scanner characterSpecifier], 0 };
+ return [NSString stringWithCString:str];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:scanner
+{
+ return (*specHandler[(int)[scanner characterSpecifier]])
+ (self, _cmd, arg, scanner);
+}
+
+@end /* DefaultEnumScannerHandler */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ FormatScanner.h
+
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+ This file is part of libFoundation.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
+*/
+
+#ifndef __FormatScanner_h__
+#define __FormatScanner_h__
+
+#include <stdarg.h>
+#include <Foundation/NSObject.h>
+
+@class NSString;
+
+/*
+ * A FormatScanner scans a NSString format. When it reaches a specifier
+ * similar to printf(3S), it calls a handler object previously registered to
+ * it. The handler object is usually inherited from the DefaultScannerHandler
+ * class. The handler object maintains a mapping between format characters and
+ * selectors that have to be called when a specifier is found in the format
+ * string. The selector must have exactly two arguments: the first one is a
+ * pointer to a va_list and the second one is the format scanner. It is the
+ * responsability of handler to increase the pointer to the va_list with the
+ * size of the object it handles. During the execution of the method the
+ * scanner calls, the handler can ask the scanner about the flags, width,
+ * precision, modifiers and the specifier character. The method should return a
+ * NSString object that represents the converted object.
+ *
+ * FormatScanner is an abstract class. Use the PrintfFormatScanner class that
+ * is used to write printf-like functions. Additional classes can be inherited
+ * to write scanf-like functions.
+ */
+
+typedef enum {
+ FS_ALTERNATE_FORM = 1,
+ FS_ZERO = 2,
+ FS_MINUS_SIGN = 4,
+ FS_PLUS_SIGN = 8,
+ FS_BLANK = 16
+} FormatScannerFlags;
+
+@interface FormatScanner : NSObject
+{
+ int specifierLen, specifierSize;
+ char *currentSpecifier;
+ id handler;
+ unsigned flags;
+ int width;
+ int precision;
+ char modifier;
+ char characterSpecifier;
+ BOOL allowFlags:1;
+ BOOL allowWidth:1;
+ BOOL allowPeriod:1;
+ BOOL allowPrecision:1;
+ BOOL allowModifier:1;
+}
+
+/* This method start the searching of specifiers in `format'. `context' is
+ passed in handleFormatSpecifierWithContext: unmodified. */
+- (BOOL)parseFormatString:(NSString*)format context:(void*)context;
+
+/* This method is called whenever a string between two specifiers is found.
+ Rewrite it in subclasses to perform whatever action you want (for example
+ to collect them in a result string if you're doing printf). The method
+ should return NO if the scanning of format should stop. */
+- (BOOL)handleOrdinaryString:(NSString*)string;
+
+/* This method is called whenever a format specifier is found in `format'.
+ Again, rewrite this method in subclasses to perform whatever action you
+ want. The method should return NO if the scanning of the format should stop.
+*/
+- (BOOL)handleFormatSpecifierWithContext:(void*)context;
+
+- (void)setFormatScannerHandler:(id)anObject;
+- (id)formatScannerHandler;
+
+- (unsigned int)flags;
+- (int)width;
+- (int)precision;
+- (char)modifier;
+- (char)characterSpecifier;
+- (const char*)currentSpecifier;
+
+- (id)setAllowFlags:(BOOL)flag;
+- (id)setAllowWidth:(BOOL)flag;
+- (id)setAllowPeriod:(BOOL)flag;
+- (id)setAllowPrecision:(BOOL)flag;
+- (id)setAllowModifier:(BOOL)flag;
+
+/* A shorthand for sending all -setAllow* messages with !flag as argument */
+- (id)setAllowOnlySpecifier:(BOOL)flag;
+
+- (BOOL)allowFlags;
+- (BOOL)allowWidth;
+- (BOOL)allowPeriod;
+- (BOOL)allowPrecision;
+- (BOOL)allowModifier;
+
+@end
+
+#endif /* __FormatScanner_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ FormatScanner.m
+
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+ This file is part of libFoundation.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
+*/
+
+#include <ctype.h>
+
+#include "common.h"
+
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSValue.h>
+#import <Foundation/NSCharacterSet.h>
+
+//#include <extensions/support.h>
+#include "FormatScanner.h"
+
+@implementation FormatScanner
+
+enum { SPECIFIER_SIZE = 1000 }; /* This value should be sufficient */
+
+- (id)init {
+ specifierSize = SPECIFIER_SIZE;
+ currentSpecifier = MallocAtomic(specifierSize);
+ allowFlags = YES;
+ allowWidth = YES;
+ allowPeriod = YES;
+ allowPrecision = YES;
+ allowModifier = YES;
+ return self;
+}
+
+- (void)dealloc {
+ if (self->currentSpecifier) free(currentSpecifier);
+ RELEASE(self->handler);
+ [super dealloc];
+}
+
+- (void)setFormatScannerHandler:(id)anObject {
+ ASSIGN(self->handler, anObject);
+}
+
+- (id)setAllowOnlySpecifier:(BOOL)flag {
+ allowFlags = !flag;
+ allowWidth = !flag;
+ allowPeriod = !flag;
+ allowPrecision = !flag;
+ allowModifier = !flag;
+ return self;
+}
+
+- (id)setAllowFlags:(BOOL)flag {
+ allowFlags = flag;
+ return self;
+}
+- (BOOL)allowFlags {
+ return allowFlags;
+}
+
+- (id)setAllowWidth:(BOOL)flag {
+ allowWidth = flag;
+ return self;
+}
+- (BOOL)allowWidth {
+ return allowWidth;
+}
+
+- (id)setAllowPeriod:(BOOL)flag {
+ allowPeriod = flag;
+ return self;
+}
+- (BOOL)allowPeriod {
+ return allowPeriod;
+}
+
+- (id)setAllowPrecision:(BOOL)flag {
+ allowPrecision = flag;
+ return self;
+}
+- (BOOL)allowPrecision {
+ return allowPrecision;
+}
+
+- (id)setAllowModifier:(BOOL)flag {
+ allowModifier = flag;
+ return self;
+}
+- (BOOL)allowModifier {
+ return allowModifier;
+}
+
+- (id)formatScannerHandler {
+ return handler;
+}
+
+- (unsigned int)flags {
+ return self->flags;
+}
+- (int)width {
+ return self->width;
+}
+- (int)precision {
+ return self->precision;
+}
+- (char)modifier {
+ return self->modifier;
+}
+- (char)characterSpecifier {
+ return self->characterSpecifier;
+}
+- (const char *)currentSpecifier {
+ return self->currentSpecifier;
+}
+
+#define CHECK_END \
+ if(i >= length) { \
+ /* An unterminated specifier. Break the loop. */ \
+ [self handleOrdinaryString: \
+ [NSString stringWithCString:currentSpecifier]]; \
+ goto _return; \
+ }
+
+/* Scans the format string looking after specifiers. Doesn't handle '*' as a
+ valid width or precision. */
+- (BOOL)parseFormatString:(NSString*)format context:(void *)context {
+ NSRange searchRange, foundRange;
+ int i, length;
+ unichar ch;
+ NSCharacterSet *decimals;
+
+ i = 0;
+ length = [format length];
+ decimals = [NSCharacterSet decimalDigitCharacterSet];
+
+ *currentSpecifier = 0;
+ specifierLen = 0;
+
+ while (i < length) {
+ searchRange.location = i;
+ searchRange.length = length - i;
+
+ foundRange = [format rangeOfString:@"%" options:0 range:searchRange];
+ if (foundRange.length == 0)
+ foundRange.location = length;
+ searchRange.length = foundRange.location - searchRange.location;
+
+ if (searchRange.length) {
+ if (![self handleOrdinaryString:
+ [format substringWithRange:searchRange]])
+ return NO;
+ }
+
+ i = foundRange.location;
+ CHECK_END
+
+ i++;
+ strcpy(currentSpecifier, "%");
+ specifierLen = 1;
+ CHECK_END
+
+ flags = width = precision = modifier = characterSpecifier = 0;
+
+ /* Check for flags. */
+ if (self->allowFlags) {
+ for (; i < length; i++) {
+ ch = [format characterAtIndex:i];
+ switch(ch) {
+ case '#': strcat(currentSpecifier, "#");
+ flags |= FS_ALTERNATE_FORM;
+ break;
+ case '0': strcat(currentSpecifier, "0");
+ flags |= FS_ZERO;
+ break;
+ case '-': strcat(currentSpecifier, "-");
+ flags |= FS_MINUS_SIGN;
+ break;
+ case '+': strcat(currentSpecifier, "+");
+ flags |= FS_PLUS_SIGN;
+ break;
+ case ' ': strcat(currentSpecifier, " ");
+ flags |= FS_BLANK;
+ break;
+ default: goto quit;
+ }
+ if (++specifierLen == specifierSize) {
+ currentSpecifier =
+ Realloc(currentSpecifier,
+ specifierSize += SPECIFIER_SIZE);
+ }
+ }
+ quit:
+ CHECK_END
+ }
+
+ /* Check for width. */
+ if (self->allowWidth) {
+ for(; i < length; i++) {
+ char str[2] = { 0, 0 };
+
+ ch = [format characterAtIndex:i];
+ if (![decimals characterIsMember:ch])
+ break;
+ str[0] = ch;
+
+ strcat(currentSpecifier, str);
+ if(++specifierLen == specifierSize) {
+ currentSpecifier =
+ Realloc(currentSpecifier,
+ specifierSize += SPECIFIER_SIZE);
+ }
+
+ width = 10 * width + (ch - '0');
+ }
+ CHECK_END
+ }
+
+ /* Check for period. */
+ if (self->allowPeriod) {
+ ch = [format characterAtIndex:i];
+ if(ch == '.') {
+ char str[2] = { ch, 0 };
+
+ strcat(currentSpecifier, str);
+ if(++specifierLen == specifierSize) {
+ currentSpecifier =
+ Realloc(currentSpecifier,
+ specifierSize += SPECIFIER_SIZE);
+ }
+
+ i++;
+ CHECK_END
+ }
+ }
+
+ /* Check for precision. */
+ if (self->allowPrecision) {
+ for(; i < length; i++) {
+ char str[2] = { 0, 0 };
+
+ ch = [format characterAtIndex:i];
+ if (![decimals characterIsMember:ch])
+ break;
+ str[0] = ch;
+
+ strcat(currentSpecifier, str);
+ if(++specifierLen == specifierSize) {
+ currentSpecifier =
+ Realloc(currentSpecifier,
+ specifierSize += SPECIFIER_SIZE);
+ }
+ precision = 10 * precision + (ch - '0');
+ }
+ CHECK_END
+ }
+
+ /* Check for data-width modifier. */
+ if (allowModifier) {
+ ch = [format characterAtIndex:i];
+ if (ch == 'h' || ch == 'l') {
+ char str[2] = { ch, 0 };
+
+ strcat(currentSpecifier, str);
+ if (++specifierLen == specifierSize) {
+ currentSpecifier =
+ Realloc(currentSpecifier,
+ specifierSize += SPECIFIER_SIZE);
+ }
+
+ modifier = ch;
+ i++;
+ CHECK_END
+ }
+ }
+
+ /* Finally, the conversion character. */
+ {
+ char str[2] = { 0, 0 };
+ ch = [format characterAtIndex:i];
+ str[0] = ch;
+
+ strcat(currentSpecifier, str);
+ if(++specifierLen == specifierSize) {
+ currentSpecifier =
+ Realloc(currentSpecifier,
+ specifierSize += SPECIFIER_SIZE);
+ }
+
+ characterSpecifier = ch;
+ }
+
+ if (![self handleFormatSpecifierWithContext:context])
+ return NO;
+
+ i++;
+ *currentSpecifier = 0;
+ specifierLen = 0;
+
+ CHECK_END
+ }
+
+_return:
+ return YES;
+}
+
+- (BOOL)handleOrdinaryString:(NSString*)string
+{
+ return YES;
+}
+
+- (BOOL)handleFormatSpecifierWithContext:(void*)context
+{
+ return YES;
+}
+
+@end /* FormatScanner */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+# $Id: GNUmakefile 1 2004-08-20 10:38:46Z znek $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+SUBPROJECT_NAME = FoundationExt
+
+FoundationExt_OBJC_FILES = \
+ DefaultScannerHandler.m \
+ PrintfFormatScanner.m \
+ FormatScanner.m \
+
+ADDITIONAL_INCLUDE_DIRS += -I. -I..
+
+include $(GNUSTEP_MAKEFILES)/subproject.make
--- /dev/null
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
--- /dev/null
+/*
+ PrintfFormatScanner.h
+
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+ This file is part of libFoundation.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
+*/
+
+#ifndef __PrintfFormatScanner_h__
+#define __PrintfFormatScanner_h__
+
+#if XCODE_SELF_COMPILE
+# include "FormatScanner.h"
+#else
+# include <FoundationExt/FormatScanner.h>
+#endif
+
+@class NSMutableString;
+
+@interface PrintfFormatScanner : FormatScanner
+{
+ NSMutableString *result;
+}
+
+- (NSString *)stringWithFormat:(NSString *)format arguments:(va_list)args;
+
+@end
+
+#endif /* __PrintfFormatScanner_h__ */
+
+/*
+ Local Variables:
+ c-basic-offset: 4
+ tab-width: 8
+ End:
+*/
--- /dev/null
+/*
+ PrintfFormatScanner.m
+
+ Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+ All rights reserved.
+
+ Author: Ovidiu Predescu <ovidiu@apache.org>
+
+ This file is part of libFoundation.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ We disclaim all warranties with regard to this software, including all
+ implied warranties of merchantability and fitness, in no event shall
+ we be liable for any special, indirect or consequential damages or any
+ damages whatsoever resulting from loss of use, data or profits, whether in
+ an action of contract, negligence or other tortious action, arising out of
+ or in connection with the use or performance of this software.
+*/
+
+#import <Foundation/NSString.h>
+#include "PrintfFormatScanner.h"
+#include "DefaultScannerHandler.h"
+
+@implementation PrintfFormatScanner
+
+- (NSString *)stringWithFormat:(NSString *)format arguments:(va_list)args {
+ va_list va;
+
+#ifdef __va_copy
+ __va_copy(va, args);
+#else
+ va = args;
+#endif
+
+ self->result = [NSMutableString stringWithCapacity:[format cStringLength]];
+ [self parseFormatString:format context:&va];
+ return [[self->result copy] autorelease];
+}
+
+- (BOOL)handleOrdinaryString:(NSString *)string {
+ [self->result appendString:string];
+ return YES;
+}
+
+- (BOOL)handleFormatSpecifierWithContext:(void *)context {
+ [self->result appendString:[handler stringForArgument:context scanner:self]];
+ return YES;
+}
+
+@end /* PrintfFormatScanner */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>GDLAccess</string>
+ <key>CFBundleGetInfoString</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>org.opengroupware.gnustep-db</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string></string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
--- /dev/null
+2004-06-28 Helge Hess <helge.hess@opengroupware.org>
+
+ * GNUmakefile.preamble: fixed link pathes (v4.2.28)
+
+2002-08-15 Helge Hess <helge.hess@skyrix.com>
+
+ * GNUmakefile: fixed Version imports (now v4.2.3)
+
+Mon Apr 2 22:02:05 2001 Helge Hess <helge.hess@skyrix.com>
+
+ * GDLExtensions.m: fixed linking problem
+
+Tue Feb 29 19:06:44 2000 Helge Hess <helge.hess@mdlink.de>
+
+ * MOF3 import
+
+Mon Apr 26 14:00:01 1999 Helge Hess <helge@trex.mdlink.de>
+
+ * added kit class GDLExtensions
+
+ * use #include instead of #import
+
+Mon Dec 21 19:02:16 1998 Helge Hess <helge@trex.mdlink.de>
+
+ * NSObject+EONullInit.m: added -stringValue to EONull
+
+Mon Dec 21 16:19:18 1998 Helge Hess <helge@trex.mdlink.de>
+
+ * EOGenericRecord+KeyValueCoding2.m: updated for new EOGenericRecord
+ classes (which uses NSMapTable instead of a dictionary).
+
+Fri Dec 11 16:48:10 1998 Helge Hess <helge@trex.mdlink.de>
+
+ * NSObject+EONullInit.m: added method '-isNull' to EONull, NSObject
+
+Fri Nov 27 19:55:21 1998 Helge Hess <helge@trex.mdlink.de>
+
+ * added PB.project
+
+Fri Nov 27 19:55:12 1998 Helge Hess <helge@trex.mdlink.de>
+
+ * created ChangeLog
+
+
--- /dev/null
+// $Id: EOEntity+Factory.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __GDLExtensions_EOEntity_Factory_P_H__
+#define __GDLExtensions_EOEntity_Factory_P_H__
+
+#include <EOAccess/EOEntity+Factory.h>
+
+#endif /* __GDLExtensions_EOEntity_Factory_H__ */
--- /dev/null
+// $Id: GDLExtensions.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __GDLExtensions_H__
+#define __GDLExtensions_H__
+
+#if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
+# include <GDLAccess/EOEntity+Factory.h>
+# include <GDLAccess/NSObject+EONullInit.h>
+#else
+# include <GDLExtensions/EOEntity+Factory.h>
+# include <GDLExtensions/NSObject+EONullInit.h>
+#endif
+
+// kit class
+
+@interface GDLExtensions : NSObject
+@end
+
+#define LINK_GDLExtensions
+
+#endif /* __GDLExtensions_H__ */
--- /dev/null
+// $Id: GDLExtensions.m 1 2004-08-20 10:38:46Z znek $
+
+#include "GDLExtensions.h"
+
+@implementation GDLExtensions
+
+- (void)_staticLinkClasses {
+}
+
+- (void)_staticLinkModules {
+}
+
+@end
--- /dev/null
+# $Id: GNUmakefile 1 2004-08-20 10:38:46Z znek $
+
+SKYROOT=../..
+
+include $(GNUSTEP_MAKEFILES)/common.make
+include $(SKYROOT)/Version
+-include ../Version
+-include ./Version
+
+LIBRARY_NAME = libGDLExtensions
+
+libGDLExtensions_HEADER_FILES = \
+ GDLExtensions.h \
+ EOEntity+Factory.h \
+ NSObject+EONullInit.h \
+
+libGDLExtensions_OBJC_FILES = GDLExtensions.m
+
+libGDLExtensions_HEADER_FILES_DIR = .
+libGDLExtensions_HEADER_FILES_INSTALL_DIR = /GDLExtensions
+libGDLExtensions_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/library.make
+-include GNUmakefile.postamble
--- /dev/null
+# $Id: GNUmakefile.preamble 1 2004-08-20 10:38:46Z znek $
+
+libGDLExtensions_INCLUDE_DIRS += \
+ -I.. -I../GDLAccess -I../..
+
+ADDITIONAL_LIB_DIRS += \
+ -L../$(GNUSTEP_OBJ_DIR) \
+ -L../../../../SOPE/skyrix-core/EOControl/$(GNUSTEP_OBJ_DIR)
+
+libGDLExtensions_LIBRARIES_DEPEND_UPON += \
+ -lGDLAccess \
+ -lEOControl
+
+ifeq ($(GNUSTEP_TARGET_OS),mingw32)
+libGDLExtensions_LIBRARIES_DEPEND_UPON += -lobjc
+endif
--- /dev/null
+// $Id: NSObject+EONullInit.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __GDLExtensions_NSObject_EONull_P_H__
+#define __GDLExtensions_NSObject_EONull_P_H__
+
+#include <EOAccess/NSObject+EONullInit.h>
+
+#endif /* __GDLExtensions_NSObject_EONull_H__ */
--- /dev/null
+// $Id: common.h 1 2004-08-20 10:38:46Z znek $
+
+// common include files
+
+#import <Foundation/Foundation.h>
+#import <EOAccess/EOAccess.h>
+
+#if NeXT_Foundation_LIBRARY
+# import <extensions/NSObjectMacros.h>
+#endif
--- /dev/null
+EXPORTS
+ __objc_class_name_GDLExtensions;
--- /dev/null
+# $Id: GNUmakefile 1 2004-08-20 10:38:46Z znek $
+
+include ../common.make
+-include ./Version
+
+GNUSTEP_INSTALLATION_DIR = ${GNUSTEP_LOCAL_ROOT}
+
+LIBRARY_NAME = libGDLAccess
+libGDLAccess_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
+
+libGDLAccess_DLL_DEF = libGDLAccess.def
+
+libGDLAccess_HEADER_FILES = \
+ GDLAccess.h \
+ EOAccess.h \
+ EODelegateResponse.h \
+ EOJoinTypes.h \
+ EOAdaptor.h \
+ EOAdaptorChannel.h \
+ EOAdaptorContext.h \
+ EOArrayProxy.h \
+ EOAttribute.h \
+ EOAttributeOrdering.h \
+ EOCustomValues.h \
+ EODatabase.h \
+ EODatabaseChannel.h \
+ EODatabaseContext.h \
+ EOEntity.h \
+ EOExpressionArray.h \
+ EOFExceptions.h \
+ EODatabaseFault.h \
+ EODatabaseFaultResolver.h \
+ EOModel.h \
+ EOObjectUniquer.h \
+ EOPrimaryKeyDictionary.h \
+ EOSQLQualifier.h \
+ EOQuotedExpression.h \
+ EORelationship.h \
+ EOSQLExpression.h \
+ EOGenericRecord.h \
+ EOModelGroup.h \
+ EONull.h \
+ EOKeySortOrdering.h \
+ EOAdaptorDataSource.h \
+ EOAdaptorChannel+Attributes.h \
+ EOAdaptorOperation.h \
+ EOAdaptorGlobalID.h \
+ NSObject+EONullInit.h \
+ EOEntity+Factory.h \
+ EORecordDictionary.h \
+ EOFault.h \
+ EOFaultHandler.h \
+
+libGDLAccess_OBJC_FILES = \
+ eoaccess.m \
+ EOAdaptor.m \
+ EOAdaptorChannel.m \
+ EOAdaptorContext.m \
+ EOArrayProxy.m \
+ EOAttribute.m \
+ EOAttributeOrdering.m \
+ EOCustomValues.m \
+ EODatabase.m \
+ EODatabaseChannel.m \
+ EODatabaseContext.m \
+ EOEntity.m \
+ EOExpressionArray.m \
+ EOFExceptions.m \
+ EODatabaseFault.m \
+ EODatabaseFaultResolver.m \
+ EOKeySortOrdering.m \
+ EOModel.m \
+ EOObjectUniquer.m \
+ EOPrimaryKeyDictionary.m \
+ EORelationship.m \
+ EOGenericRecord.m \
+ EOModelGroup.m \
+ EOEntityClassDescription.m \
+ EOAdaptorDataSource.m \
+ EOAdaptorChannel+Attributes.m \
+ EOAdaptorOperation.m \
+ EOAdaptorGlobalID.m \
+ NSObject+EONullInit.m \
+ EOEntity+Factory.m \
+ EORecordDictionary.m \
+ EOFault.m \
+ EOFaultHandler.m \
+ \
+ EOAndQualifier+SQL.m \
+ EOKeyComparisonQualifier+SQL.m \
+ EOKeyValueQualifier+SQL.m \
+ EONotQualifier+SQL.m \
+ EOOrQualifier+SQL.m \
+ EOQualifier+SQL.m \
+ \
+ EOSQLQualifier.m \
+ EOSQLExpression.m \
+ EOSelectSQLExpression.m \
+ EOQuotedExpression.m \
+ EOQualifierScanner.m \
+
+ifneq ($(FOUNDATION_LIB),fd)
+libGDLAccess_SUBPROJECTS += FoundationExt
+endif
+
+libGDLAccess_HEADER_FILES_DIR = EOAccess
+libGDLAccess_HEADER_FILES_INSTALL_DIR = /GDLAccess
+
+# GDLExtensions
+
+SUBPROJECTS += GDLExtensions
+
+# adaptor load test
+
+TOOL_NAME = load-EOAdaptor connect-EOAdaptor
+
+load-EOAdaptor_OBJC_FILES = load-EOAdaptor.m
+load-EOAdaptor_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR)
+load-EOAdaptor_TOOL_LIBS += -lGDLAccess -lEOControl
+
+connect-EOAdaptor_OBJC_FILES = connect-EOAdaptor.m
+connect-EOAdaptor_LIB_DIRS += -L./$(GNUSTEP_OBJ_DIR)
+connect-EOAdaptor_TOOL_LIBS += -lGDLAccess -lEOControl
+
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/library.make
+include $(GNUSTEP_MAKEFILES)/aggregate.make
+include $(GNUSTEP_MAKEFILES)/tool.make
+-include GNUmakefile.postamble
--- /dev/null
+# $Id: GNUmakefile.postamble 1 2004-08-20 10:38:46Z znek $
+
+ifneq ($(GNUSTEP_TARGET_OS),cygwin32)
+
+before-all ::
+ $(LN_S) -f EOAccess GDLAccess
+
+after-install ::
+ cp -rf \
+ $(GNUSTEP_HEADERS)$(libGDLAccess_HEADER_FILES_INSTALL_DIR) \
+ $(GNUSTEP_HEADERS)/EOAccess
+
+endif
+
+ifneq ($(FOUNDATION_LIB),nx)
+# case sensitivity issues on HFS ...
+
+after-install ::
+ cp -rf \
+ $(GNUSTEP_HEADERS)$(libGDLAccess_HEADER_FILES_INSTALL_DIR) \
+ $(GNUSTEP_HEADERS)/eoaccess
+
+endif
--- /dev/null
+# $Id: GNUmakefile.preamble 1 2004-08-20 10:38:46Z znek $
+
+libGDLAccess_LIBRARIES_DEPEND_UPON = \
+ -lEOControl
+
+libGDLAccess_LIB_DIRS += \
+ -L../../../SOPE/skyrix-core/EOControl/$(GNUSTEP_OBJ_DIR)
+
+ifeq ($(GNUSTEP_TARGET_OS),mingw32)
+libGDLAccess_LIBRARIES_DEPEND_UPON += -lobjc
+endif
+
+ifeq ($(GNUSTEP_TARGET_OS),cygwin32)
+libGDLAccess_LIBRARIES_DEPEND_UPON += -lobjc
+endif
+
+libGDLAccess_INCLUDE_DIRS += \
+ -I. \
+ -I./$(libGDLAccess_HEADER_FILES_DIR) \
+ -I.. \
+ -I../../../SOPE/skyrix-core/ \
+ -IFoundationExt
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: NSObject+EONullInit.m 1 2004-08-20 10:38:46Z znek $
+
+#include <GDLAccess/NSObject+EONullInit.h>
+#include <GDLAccess/EOEntity+Factory.h>
+#include "common.h"
+
+@interface NSObject(Entity)
+- (EOEntity *)entity;
+@end
+
+@implementation NSObject(EONullInit)
+
+- (void)setAllAttributesToEONull:(EOEntity *)_entity {
+ NSAssert(_entity != nil, @"invalid entity parameter");
+ [_entity setAttributesOfObjectToEONull:self];
+}
+
+- (void)setAllAttributesToEONull {
+ // assume the object respondsTo: entity
+ [self setAllAttributesToEONull:[self entity]];
+}
+
+@end /* NSObject(EONullInit) */
--- /dev/null
+# $Id: README 1 2004-08-20 10:38:46Z znek $
+
+NOTE: this file is heavily outdated
+
+GNU Database Library Access Layer - MDlink patch Version
+
+ Contained code is derived from gdl - GNU Database Library and is therefore
+ LGPL license. Copyright for gdl has the Free Software Foundation.
+
+ Changes
+
+ There are no EOJoin's anymore (only for compability). EORelationships cannot
+ be compound and store source and destination themselves.
+
+ No compound primary keys are allowed.
+
+ Uniquing is always enabled.
+
+ Static Linking
+
+ uncomment '#imports' in EOModel.m
+
+ Intro
+
+ The GNUstep Database Library is a hierarchy of Objective-C classes
+ that provide a three-tiered architecture for developing database
+ applications.
+
+ The three-tier architecture is a flexible paradigm for building
+ robust and scalable client/server applications; the three tiers refer
+ to the database, the Application Objects, and the user interface. The
+ separation of the database from the user interface through intermediary
+ Application Objects allows the data to be distributed appropriately
+ across database servers and still have the user interface display data
+ cohesively for the end-user. Business logic, as implemented in the
+ Application Objects, provides the mechanism for consistency and
+ reusability across all your business applications.
+
+ Entity-relationship modelling is used for describing the Application
+ Objects and how they are mapped to database fields. The GNUstep
+ Database Library represents these models as plain ASCII text files; this
+ allows external programs to be used for constructing and maintaining the
+ models separate from the applications which use them.
+
+ Differences to GNUstep gdl
+
+ Datasource objects are missing.
+
+ ToDo
+
+ EOQualifier:
+ `isValidQualifierType' from EOAdaptor is not used now. This method
+ is supposed to verify, when a qualifier is constructed, if an
+ attribute can appear inside an expression.
+
+ Make the relationshipPaths of type GCMutableSet.
+
+ EOSQLExpresion
+ There is no support now for specifying properties for the tables
+ that appear in the FROM clause; I am thinking specifically at the
+ OUTER specifier required by some servers when you use outer joins.
+
+ Optimize the generated WHERE clause when the same relationship
+ appears more than one time in the entity.
+
+ The external query from EOEntity is not used when a fetch
+ operation is unrestricted, i.e. it fetches all the records from
+ the table
+
+ Class Hierachy
+
+ NSObject
+ DefaultScannerHandler
+ EOInsertUpdateScannerHandler
+ EOQualifierScannerHandler
+ EOSelectScannerHandler
+ EOAdaptor
+ EOAdaptorChannel
+ EOAdaptorContext
+ EOAttributeOrdering
+ EODatabase
+ EODatabaseChannel
+ EODatabaseContext
+ EOFaultResolver
+ EOArrayFault
+ EOObjectFault
+ EOGenericRecord
+ EOKeySortOrdering
+ EONull < NSCopying >
+ EOObjectUniquer
+ EOQualifierJoinHolder
+ EOQuotedExpression < NSCopying >
+ EOSQLExpression < EOExpressionContext >
+ EODeleteSQLExpression
+ EOInsertSQLExpression
+ EOSelectSQLExpression
+ EOUpdateSQLExpression
+ NSDictionary
+ EOPrimaryKeyDictionary
+ EOSinglePrimaryKeyDictionary
+ EOMultiplePrimaryKeyDictionary
+ NSEnumerator
+ EOSinglePrimaryKeyDictionaryEnumerator
+ EOAttribute
+ EOEntity
+ EOModel
+ EOQualifier
+ EOSQLQualifier < NSCopying >
+ EORelationship
+ EOExpressionArray
+
+ GCObject
+ GCMutableArray
+
+ EOFault
+
+ NSException
+ EOFException
+ DestinationEntityDoesntMatchDefinitionException
+ EOAdaptorException
+ InvalidAttributeException
+ InvalidQualifierException
+ ObjectNotAvailableException
+ PropertyDefinitionException
+ PropertyDefinitionException
+ InvalidNameException
+ InvalidPropertyException
+ InvalidValueTypeException
+ RelationshipMustBeToOneException
+ EOAdaptorException
+ CannotFindAdaptorBundleException
+ DataTypeMappingNotSupportedException
+ InvalidAdaptorBundleException
+ InvalidAdaptorStateException
+ InvalidAdaptorStateException
+ AdaptorIsFetchingException
+ AdaptorIsNotFetchingException
+ ChannelIsNotOpenedException
+ NoTransactionInProgressException
+ TooManyOpenedChannelsException
+
+ Categories
+
+ EOAdaptor+Private
+ EOAdaptorContext+Private
+ EOAttribute+EOAttributePrivate
+ EOAttribute+ValuesConversion
+ EODatabase+Private
+ EODatabaseChannel+Private
+ EODatabaseContext+Private
+ EOEntity+EOEntityPrivate
+ EOEntity+ValuesConversion
+ EOJoin+EOJoinPrivate
+ EOModel+EOModelPrivate
+ EORelationship+EORelationshipPrivate
+ NSArray+EOKeyBasedSorting
+ NSData+EOCustomValues
+ NSDictionary+EOKeyValueCoding
+ NSMutableArray+EOKeyBasedSorting
+ NSMutableDictionary+EOKeyValueCoding
+ NSNumber+EOCustomValues
+ NSObject+EOExpression
+ NSObject+EOAdaptorChannelDelegation
+ NSObject+EOAdaptorContextDelegate
+ NSObject+EOAdaptorDelegate
+ NSObject+EOCustomValues
+ NSObject+EODatabaseChannelDelegateProtocol
+ NSObject+EODatabaseChannelNotification
+ NSObject+EODatabaseCustomValues
+ NSObject+EOGenericRecord
+ NSObject+EOKeyValueCoding
+ NSObject+EOKeyValueCodingEONull
+ NSObject+EOUnableToFaultToOne
+ NSString+EOAttributeTypeCheck
+ NSString+EOCustomValues
+
+ Protocols
+
+ EOExpressionContext
+
+ Informal Protocols
+
+ EOClassMapping
+ EOCustomValues
+ EODatabaseChannelNotification
+ EODatabaseCustomValues
+ EOExpression
+ EOKeyValueCoding
+ EOKeyValueCodingEONull
+ EOUnableToFaultToOne
+
+--
+Helge Hess (helge@mdlink.de)
+MDlink online service center, 1998-11-01
--- /dev/null
+# $Id: TODO 1 2004-08-20 10:38:46Z znek $
+
+TODO
+====
+
+- remove all things not required for OGo
+
+MacOSX
+======
+
+- replace all InvalidArgumentExceptions with proper Foundation replacements
+
+- remove dependency on FoundationExt
+ - currently the dependency is formed by the libFoundation scanner handlers
+ and format processors
--- /dev/null
+# $Id: Version 1 2004-08-20 10:38:46Z znek $
+
+SUBMINOR_VERSION:=32
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: common.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef __common_h__
+#define __common_h__
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef __WIN32__
+# include <unistd.h>
+# include <pwd.h>
+#endif
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#import <Foundation/NSZone.h>
+#import <Foundation/Foundation.h>
+#import <Foundation/NSUtilities.h>
+#import <Foundation/NSObjCRuntime.h>
+
+#if NeXT_RUNTIME || APPLE_RUNTIME
+# define sel_eq(sela,selb) (sela==selb?YES:NO)
+#endif
+
+#if LIB_FOUNDATION_LIBRARY
+# import <Foundation/exceptions/GeneralExceptions.h>
+# import <extensions/objc-runtime.h>
+#else
+# include <NGExtensions/NGObjectMacros.h>
+# include <NGExtensions/NSString+Ext.h>
+#endif
+
+
+// ******************** common functions ********************
+
+static inline void *Malloc(int) __attribute__((unused));
+static inline void *Calloc(int, int) __attribute__((unused));
+static inline void *Realloc(void*, int) __attribute__((unused));
+static inline void Free(void*) __attribute__((unused));
+
+static inline int Strlen(const char*) __attribute__((unused));
+static inline char* Strdup(const char*) __attribute__((unused));
+static inline char* Strcpy (char*, const char*) __attribute__((unused));
+static inline char* Strncpy (char*, const char*, unsigned)
+ __attribute__((unused));
+static inline char* Strcat (char*, const char*) __attribute__((unused));
+static inline char* Strncat (char*, const char*, unsigned)
+ __attribute__((unused));
+static inline int Strcmp(const char*, const char*) __attribute__((unused));
+static inline int Strncmp(const char*, const char*, unsigned)
+ __attribute__((unused));
+static inline int Atoi(const char*) __attribute__((unused));
+static inline long Atol(const char*) __attribute__((unused));
+
+static inline void *Malloc(int size) {
+ return malloc(size);
+}
+
+static inline void *MallocAtomic(int size) {
+ return malloc(size);
+}
+
+static inline void Free(void* p) {
+ if (p) free(p);
+}
+
+static inline void *Calloc(int elem, int size) {
+ return calloc(elem, size);
+}
+
+static inline void *CallocAtomic(int elem, int size) {
+ return calloc(elem, size);
+}
+
+static inline void *Realloc(void* p, int size) {
+ return realloc(p, size);
+}
+
+static inline int Strlen(const char* s) {
+ return s ? strlen(s) : 0;
+}
+
+static inline char* Strdup(const char* s) {
+ return s ? strcpy(Malloc(strlen(s) + 1), s) : NULL;
+}
+
+static inline char* Strcpy (char* d, const char* s) {
+ return s && d ? strcpy(d, s) : d;
+}
+
+static inline char* Strncpy (char* d, const char* s, unsigned size) {
+ return s && d ? strncpy(d, s, size) : d;
+}
+
+static inline char* Strcat (char* d, const char* s) {
+ return s && d ? strcat(d, s) : d;
+}
+
+static inline char* Strncat (char* d, const char* s , unsigned size) {
+ return s && d ? strncat(d, s , size) : d;
+}
+
+static inline int Strcmp(const char* p, const char* q) {
+ if(!p) {
+ if(!q)
+ return 0;
+ else return -1;
+ }
+ else {
+ if(!q)
+ return 1;
+ else return strcmp(p, q);
+ }
+}
+
+static inline int Strncmp(const char* p, const char* q, unsigned size) {
+ if(!p) {
+ if(!q)
+ return 0;
+ else return -1;
+ }
+ else {
+ if(!q)
+ return 1;
+ else return strncmp(p, q, size);
+ }
+}
+
+static inline int Atoi(const char* str)
+{
+ return str ? atoi(str) : 0;
+}
+
+static inline long Atol(const char *str)
+{
+ return str ? atol(str) : 0;
+}
+
+#ifndef MAX
+#define MAX(a, b) \
+ ({typedef _ta = (a), _tb = (b); \
+ _ta _a = (a); _tb _b = (b); \
+ _a > _b ? _a : _b; })
+#endif
+
+#ifndef MIN
+#define MIN(a, b) \
+ ({typedef _ta = (a), _tb = (b); \
+ _ta _a = (a); _tb _b = (b); \
+ _a < _b ? _a : _b; })
+#endif
+
+#if !LIB_FOUNDATION_LIBRARY
+
+#ifndef CREATE_AUTORELEASE_POOL
+#define CREATE_AUTORELEASE_POOL(pool) \
+ id pool = [[NSAutoreleasePool alloc] init]
+#endif
+
+#endif /* ! LIB_FOUNDATION_LIBRARY */
+
+
+#if !LIB_FOUNDATION_LIBRARY
+
+static inline char *Ltoa(long nr, char *str, int base)
+{
+ char buff[34], rest, is_negative;
+ int ptr;
+
+ ptr = 32;
+ buff[33] = '\0';
+ if(nr < 0) {
+ is_negative = 1;
+ nr = -nr;
+ }
+ else
+ is_negative = 0;
+
+ while(nr != 0) {
+ rest = nr % base;
+ if(rest > 9)
+ rest += 'A' - 10;
+ else
+ rest += '0';
+ buff[ptr--] = rest;
+ nr /= base;
+ }
+ if(ptr == 32)
+ buff[ptr--] = '0';
+ if(is_negative)
+ buff[ptr--] = '-';
+
+ Strcpy(str, &buff[ptr+1]);
+
+ return(str);
+}
+#endif
+
+#if !LIB_FOUNDATION_LIBRARY
+
+@interface NSObject(FoundationExtGDLAccess)
+- (void)subclassResponsibility:(SEL)sel;
+- (void)notImplemented:(SEL)sel;
+@end
+
+#endif
+
+#if !GNU_RUNTIME
+# ifndef SEL_EQ
+# define SEL_EQ(__A__,__B__) (__A__==__B__ ? YES : NO)
+# endif
+#else
+# ifndef SEL_EQ
+# include <objc/objc.h>
+# define SEL_EQ(__A__,__B__) sel_eq(__A__,__B__)
+# endif
+#endif
+
+#endif /* __common_h__ */
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: connect-EOAdaptor.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/Foundation.h>
+#include <GDLAccess/EOAdaptor.h>
+#include <GDLAccess/EOAdaptorContext.h>
+#include <GDLAccess/EOAdaptorChannel.h>
+#include <stdio.h>
+
+int main(int argc, char **argv, char **env) {
+ NSAutoreleasePool *pool;
+ NSArray *args;
+ NSString *adaptorName;
+ NSString *condictstr;
+ NSDictionary *condict;
+ EOAdaptor *adaptor;
+ EOAdaptorContext *adctx;
+ EOAdaptorChannel *adch;
+ BOOL ok;
+
+ pool = [[NSAutoreleasePool alloc] init];
+#if LIB_FOUNDATION_LIBRARY
+ [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+ args = [[NSProcessInfo processInfo] arguments];
+ if ([args count] < 3) {
+ fprintf(stderr, "usage: %s adaptorname condict\n", argv[0]);
+ exit(10);
+ }
+
+ adaptorName = [args objectAtIndex:1];
+ condictstr = [args objectAtIndex:2];
+
+ /* load adaptor */
+
+ NS_DURING {
+ adaptor = [EOAdaptor adaptorWithName:adaptorName];
+ }
+ NS_HANDLER {
+ fprintf(stderr, "ERROR: %s: %s\n",
+ [[localException name] cString],
+ [[localException reason] cString]);
+ adaptor = nil;
+ }
+ NS_ENDHANDLER;
+
+ if (adaptor == nil) {
+ fprintf(stderr, "ERROR: failed to load adaptor '%s'.\n",
+ [adaptorName cString]);
+ exit(1);
+ }
+
+ printf("did load adaptor: %s\n", [[adaptor name] cString]);
+
+ /* setup connection dictionary */
+
+ if ((condict = [condictstr propertyList]) == nil) {
+ fprintf(stderr, "ERROR: invalid connection dictionary '%s'.\n",
+ [condictstr cString]);
+ exit(2);
+ }
+ [adaptor setConnectionDictionary:condict];
+
+ /* setup connection */
+
+ if ((adctx = [adaptor createAdaptorContext]) == nil) {
+ fprintf(stderr, "ERROR: could not create adaptor context.");
+ exit(3);
+ }
+ if ((adch = [adctx createAdaptorChannel]) == nil) {
+ fprintf(stderr, "ERROR: could not create adaptor channel.");
+ exit(4);
+ }
+
+ /* connect */
+
+ ok = NO;
+ NS_DURING {
+ ok = [adch openChannel];
+ }
+ NS_HANDLER {
+ fprintf(stderr, "ERROR: could not connect to database %s: %s\n",
+ [[localException name] cString],
+ [[localException reason] cString]);
+ exit(5);
+ }
+ NS_ENDHANDLER;
+
+ if (!ok) {
+ fprintf(stderr, "ERROR: could not connect to database.\n");
+ exit(6);
+ }
+ else
+ printf("connection could be established.\n");
+
+ [adch closeChannel];
+
+ exit(0);
+ return 0;
+}
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: eoaccess.m 1 2004-08-20 10:38:46Z znek $
+
+#include "EOAccess.h"
+#include "EOArrayProxy.h"
+
+@implementation GDLAccess
+
+- (void)_staticLinkClasses {
+ [EOAdaptor class];
+ [EOAdaptorChannel class];
+ [EOAdaptorContext class];
+ [EOArrayProxy class];
+ [EOAttribute class];
+ [EOAttributeOrdering class];
+ [EODatabase class];
+ [EODatabaseChannel class];
+ [EODatabaseContext class];
+ [EOEntity class];
+ [EOFException class];
+ [ObjectNotAvailableException class];
+ [PropertyDefinitionException class];
+ [DestinationEntityDoesntMatchDefinitionException class];
+ [InvalidNameException class];
+ [InvalidPropertyException class];
+ [RelationshipMustBeToOneException class];
+ [InvalidValueTypeException class];
+ [InvalidAttributeException class];
+ [InvalidQualifierException class];
+ [EOAdaptorException class];
+ [CannotFindAdaptorBundleException class];
+ [InvalidAdaptorBundleException class];
+ [InvalidAdaptorStateException class];
+ [DataTypeMappingNotSupportedException class];
+ [ChannelIsNotOpenedException class];
+ [AdaptorIsFetchingException class];
+ [AdaptorIsNotFetchingException class];
+ [NoTransactionInProgressException class];
+ [TooManyOpenedChannelsException class];
+ [EOModel class];
+ [EOObjectUniquer class];
+ [EOPrimaryKeyDictionary class];
+ [EOSQLQualifier class];
+ [EOQuotedExpression class];
+ [EORelationship class];
+ [EOSQLExpression class];
+#if 0
+ [EOSelectSQLExpression class];
+ [EOInsertSQLExpression class];
+ [EOUpdateSQLExpression class];
+ [EODeleteSQLExpression class];
+#endif
+}
+
+- (void)_staticLinkCategories {
+}
+
+- (void)_staticLinkModules {
+}
+
+@end /* GDLAccess */
--- /dev/null
+EXPORTS
+ __objc_class_name_EOAdaptor;
+ __objc_class_name_EOAdaptorChannel;
+ __objc_class_name_EOAdaptorContext;
+ __objc_class_name_EOArrayProxy;
+ __objc_class_name_EOAttribute;
+ __objc_class_name_EOAttributeOrdering;
+ __objc_class_name_EODatabase;
+ __objc_class_name_EODatabaseChannel;
+ __objc_class_name_EODatabaseContext;
+ __objc_class_name_EODatabaseFault;
+ __objc_class_name_EODatabaseFaultResolver;
+ __objc_class_name_EOArrayFault;
+ __objc_class_name_EOObjectFault;
+ __objc_class_name_EOEntity;
+ __objc_class_name_EOEntityClassDescription;
+ __objc_class_name_EOExpressionArray;
+ __objc_class_name_EOFException;
+ __objc_class_name_ObjectNotAvailableException;
+ __objc_class_name_PropertyDefinitionException;
+ __objc_class_name_DestinationEntityDoesntMatchDefinitionException;
+ __objc_class_name_InvalidNameException;
+ __objc_class_name_InvalidPropertyException;
+ __objc_class_name_RelationshipMustBeToOneException;
+ __objc_class_name_InvalidValueTypeException;
+ __objc_class_name_InvalidAttributeException;
+ __objc_class_name_InvalidQualifierException;
+ __objc_class_name_EOAdaptorException;
+ __objc_class_name_CannotFindAdaptorBundleException;
+ __objc_class_name_InvalidAdaptorBundleException;
+ __objc_class_name_InvalidAdaptorStateException;
+ __objc_class_name_DataTypeMappingNotSupportedException;
+ __objc_class_name_ChannelIsNotOpenedException;
+ __objc_class_name_AdaptorIsFetchingException;
+ __objc_class_name_AdaptorIsNotFetchingException;
+ __objc_class_name_NoTransactionInProgressException;
+ __objc_class_name_TooManyOpenedChannelsException;
+ __objc_class_name_EOKeySortOrdering;
+ __objc_class_name_EOModel;
+ __objc_class_name_EOModelGroup;
+ __objc_class_name_EOObjectUniquer;
+ __objc_class_name_EOSinglePrimaryKeyDictionary;
+ __objc_class_name_EOSinglePrimaryKeyDictionaryEnumerator;
+ __objc_class_name_EOMultiplePrimaryKeyDictionary;
+ __objc_class_name_EOPrimaryKeyDictionary;
+ __objc_class_name_EOQualifierScannerHandler;
+ __objc_class_name_EOQualifierEnumScannerHandler;
+ __objc_class_name_EOQuotedExpression;
+ __objc_class_name_EORelationship;
+ __objc_class_name_EOJoin;
+ __objc_class_name_EOSelectScannerHandler;
+ __objc_class_name_EOInsertUpdateScannerHandler;
+ __objc_class_name_EOSQLExpression;
+ __objc_class_name_EOSelectSQLExpression;
+ __objc_class_name_EOInsertSQLExpression;
+ __objc_class_name_EOUpdateSQLExpression;
+ __objc_class_name_EODeleteSQLExpression;
+ __objc_class_name_EOQualifierJoinHolder;
+ __objc_class_name_EOSQLQualifier;
+ __objc_class_name_eoaccess;
--- /dev/null
+/*
+ EOAdaptorChannel.m
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+ Date: October 1996
+
+ This file is part of the GNUstep Database Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: load-EOAdaptor.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/Foundation.h>
+#include <GDLAccess/EOAdaptor.h>
+#include <stdio.h>
+
+int main(int argc, char **argv, char **env) {
+ NSAutoreleasePool *pool;
+ NSArray *args;
+ NSString *adaptorName;
+ EOAdaptor *adaptor;
+
+ pool = [[NSAutoreleasePool alloc] init];
+#if LIB_FOUNDATION_LIBRARY
+ [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+ args = [[NSProcessInfo processInfo] arguments];
+ if ([args count] < 2) {
+ fprintf(stderr, "usage: %s adaptorname\n", argv[0]);
+ exit(10);
+ }
+
+ adaptorName = [args objectAtIndex:1];
+
+ NS_DURING {
+ adaptor = [EOAdaptor adaptorWithName:adaptorName];
+ }
+ NS_HANDLER {
+ fprintf(stderr, "ERROR: %s: %s\n",
+ [[localException name] cString],
+ [[localException reason] cString]);
+ adaptor = nil;
+ }
+ NS_ENDHANDLER;
+
+ if (adaptor) {
+ printf("did load adaptor: %s\n", [[adaptor name] cString]);
+ exit(0);
+ }
+
+ fprintf(stderr, "ERROR: failed to load adaptor '%s'.\n",
+ [adaptorName cString]);
+
+ exit (1);
+ return 1;
+}
--- /dev/null
+#!/usr/bin/env python
+# $Id: test.py 2 2004-08-20 10:48:47Z znek $
+from sys import *
+from Foundation import *
+from eoaccess import *
+from EOControl import *
+from NGExtensions import *
+from GDLExtensions import *
+import resource;
+
+defaults = NSUserDefaults();
+
+connDict = defaults["LSConnectionDictionary"];
+if connDict is None:
+ print "missing connection dictionary\n";
+ exit(1);
+
+primKeyGenDict = defaults["pkeyGeneratorDictionary"];
+print primKeyGenDict;
+if primKeyGenDict is None:
+ print "missing pkeyGeneratorDictionary\n";
+ exit(1);
+
+
+print "ConnectionDictionary: ";
+print connDict.description();
+
+adaptorName = defaults["LSAdaptor"];
+if adaptorName is None:
+ adaptorName = "Sybase10";
+
+adaptor = EOAdaptor(adaptorName);
+adaptor.setConnectionDictionary(connDict);
+adaptor.setPkeyGeneratorDictionary(primKeyGenDict);
+
+adContext = adaptor.createAdaptorContext();
+adChannel = adContext.createAdaptorChannel();
+
+def test_database_channel():
+ print "adChannel " + adChannel.description() + "\n";
+ print "channel ";
+ print "attributesForTableName doc";
+ print adChannel.invoke1("attributesForTableName:", "doc");
+ print "primaryKeyAttributesForTableName document _______________________________________\n";
+ print adChannel.invoke1("primaryKeyAttributesForTableName:", "document");
+ print "primaryKeyAttributesForTableName:, doc _______________________________________\n";
+ print adChannel.invoke1("primaryKeyAttributesForTableName:", "doc");
+ print "primaryKeyAttributesForTableName company _______________________________________\n";
+ print adChannel.invoke1("primaryKeyAttributesForTableName:", "company");
+ print "primaryKeyAttributesForTableName person_______________________________________\n";
+ print adChannel.invoke1("primaryKeyAttributesForTableName:", "person");
+ print "_______________________________________\n";
+
+def test_adaptor_data_source():
+ adaptor = adChannel.adaptorContext().adaptor();
+ dict = NSMutableDictionary();
+ dict["login"] = "jan_1";
+ dict["name"] = "JR";
+ dict["firstname"] = "jan";
+ dict["is_person"] = 1;
+ dict["number"] = "12345_1";
+ dict["birthday"] = NSCalendarDate('1999-09-21 13:23', '%Y-%m-%d %H:%M');
+ dict["middlename"] = "Ein Unnuetzer middlename";
+
+
+ dataSource = EOAdaptorDataSource(adChannel);
+ hints = NSMutableDictionary();
+ pks = NSMutableArray();
+ pks.addObject("company_id");
+ hints.setObjectForKey(pks, "EOPrimaryKeyAttributeNamesHint")
+
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setEntityName("company");
+ fetchSpec.setHints(hints);
+
+ dataSource.setFetchSpecification(fetchSpec);
+ print "-------------------- {insert ---------------------\n";
+ dataSource.insertObject(dict);
+ print "-------------------- insert} ---------------------\n";
+
+ print "-------------------- {select with hints ---------------------\n";
+ qualifier = EOQualifier("login = %@", ("jan_1", ))
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setQualifier(qualifier);
+ fetchSpec.setEntityName("company");
+
+ hints = NSMutableDictionary();
+ pks.addObject("company_id");
+ hints.setObjectForKey(NSTimeZone('MET'), "EOFetchResultTimeZoneHint")
+ fetchSpec.setHints(hints);
+
+ sortOrderings = NSMutableArray();
+ sortOrderings.addObject(EOSortOrdering("login", "compareCaseInsensitiveAscending:"));
+ sortOrderings.addObject(EOSortOrdering("company_id", "compareCaseInsensitiveDescending:"));
+ fetchSpec.setSortOrderings(sortOrderings);
+ dataSource = EOAdaptorDataSource(adChannel);
+ dataSource.setFetchSpecification(fetchSpec);
+ objs = dataSource.fetchObjects();
+ print objs;
+ print "-------------------- select} ---------------------\n";
+ obj = objs[0];
+
+ print "-------------------- {update ---------------------\n";
+ print obj;
+ obj["login"] = "jan_1_1";
+ obj["middlename"] = EONull();
+ dataSource.updateObject(obj);
+ print "-------------------- update} ---------------------\n";
+
+ qualifier = EOQualifier("login caseInsensitiveLike %@", ("jan_1_*", ))
+ fetchSpec.setQualifier(qualifier);
+ dataSource.setFetchSpecification(fetchSpec);
+
+ print "-------------------- {select ---------------------\n";
+ objs = dataSource.fetchObjects();
+ print objs;
+ print "-------------------- select} ---------------------\n";
+
+ print "-------------------- {delete ---------------------\n";
+ obj = objs[0];
+ dataSource.deleteObject(obj);
+ print "-------------------- delete} ---------------------\n";
+
+ print "-------------------- {select ---------------------\n";
+ objs = dataSource.fetchObjects();
+ print objs;
+ print "-------------------- select} ---------------------\n";
+
+
+def test_cascaded_datasources():
+
+ adaptor = adChannel.adaptorContext().adaptor();
+ dict = NSMutableDictionary();
+ dict["login"] = "jan_1";
+ dict["name"] = "JR";
+ dict["firstname"] = "jan";
+ dict["is_person"] = 1;
+ dict["number"] = "12345_1";
+
+ dataSource = EOAdaptorDataSource(adChannel);
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setEntityName("company");
+ qualifier = EOQualifier("login like %@", ("j%", ))
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setQualifier(qualifier);
+ fetchSpec.setEntityName("company");
+ sortOrderings = NSMutableArray();
+ sortOrderings.addObject(EOSortOrdering("login", "compareCaseInsensitiveAscending:"));
+ fetchSpec.setSortOrderings(sortOrderings);
+ hints = NSMutableDictionary();
+ pks = NSMutableArray();
+ pks.addObject("company_id");
+ hints.setObjectForKey(pks, "EOPrimaryKeyAttributeNamesHint")
+
+ fetchSpec.setHints(hints);
+
+ dataSource.setFetchSpecification(fetchSpec);
+ cacheDataSource = EOCacheDataSource(dataSource);
+ objs = dataSource.fetchObjects();
+ print objs;
+ print cacheDataSource.fetchObjects();
+ print "-----------------------------\n";
+ print cacheDataSource.fetchObjects();
+ dataSource.insertObject(dict);
+ print "++++++++++++++++++++++++++++\n";
+
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setEntityName("company");
+ qualifier = EOQualifier("login = %@", ("jan_1", ))
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setQualifier(qualifier);
+ fetchSpec.setEntityName("company");
+ dataSource.setFetchSpecification(fetchSpec);
+ cacheDataSource = EOCacheDataSource(dataSource);
+ objs = dataSource.fetchObjects();
+ obj = objs[0];
+ print objs;
+ print "-----------------------------\n";
+ print cacheDataSource.deleteObject(obj);
+ print "++++++++++++++++++++++++++++\n";
+ print cacheDataSource.fetchObjects();
+
+def echo_logins(objs):
+ for o in objs:
+ print o['login'];
+
+def test_sort_datasource():
+ dataSource = EOAdaptorDataSource(adChannel);
+
+ fetchSpec = EOFetchSpecification();
+ fetchSpec.setEntityName("company");
+ qualifier = EOQualifier("login like %@", ("%a%", ))
+ fetchSpec.setQualifier(qualifier);
+
+ dataSource.setFetchSpecification(fetchSpec);
+ echo_logins(dataSource.fetchObjects());
+
+ sortOrderings = NSMutableArray();
+ sO = EOSortOrdering("login", "compareDescending:");
+ sortOrderings.addObject(sO);
+ fetchSpec.setSortOrderings(sortOrderings);
+ dataSource.setFetchSpecification(fetchSpec);
+
+ echo_logins(dataSource.fetchObjects());
+
+print resource.getrlimit(resource.RLIMIT_CORE);
+if adChannel.openChannel():
+ print "open channel ok";
+else:
+ print "open channel failed";
+ exit(1);
+print "adChannel ", adChannel;
+
+
+#test_database_channel();
+test_adaptor_data_source();
+#test_cascaded_datasources();
+#test_sort_datasource();
--- /dev/null
+# $Id: GNUmakefile 1 2004-08-20 10:38:46Z znek $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+PACKAGE_NAME=sope-gdl1
+VERSION=4.3.0
+
+SUBPROJECTS += \
+ GDLAccess \
+ PostgreSQL72 \
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/aggregate.make
+-include GNUmakefile.postamble
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
--- /dev/null
+2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+
+ * moved from ThirdParty to SOPE/sope-gdl1 (v1.0.33)
+
+2004-07-06 Helge Hess <helge.hess@opengroupware.org>
+
+ * PostgreSQL72Channel.m: ensure that the port is passed to the
+ connection as a string object (v1.0.32)
+
+2004-06-29 Helge Hess <helge.hess@opengroupware.org>
+
+ * GNUmakefile.preamble: added include path to SOPE/skyrix-core for
+ "inline" compilation (v1.0.31)
+
+2004-06-28 Helge Hess <helge.hess@opengroupware.org>
+
+ * PostgreSQL72Channel.m: do not raise errors in handler methods, but
+ return them for processing by the new X methods (v1.0.30)
+
+ * PostgreSQL72Channel.m: implement a specific -evaluateExpressionX:,
+ use that in -primaryKeyForNewRowWithEntity: (v1.0.29)
+
+2004-06-22 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.28
+
+ * PostgreSQL72Adaptor.m: some code cleanups
+
+ * PostgreSQL72Channel+Model.m: fixed a gstep-base warning
+
+ * NSNumber+PGVal.m ([NSNumber -stringValueForPostgreSQLType:attribute:]):
+ fixed rendering of bool numbers for gstep-base (-stringValue of
+ bool numbers return 'YES'/'NO' on gstep-base while 1 or 0 on Cocoa
+ and libFoundation)
+
+2004-06-21 Helge Hess <helge.hess@opengroupware.org>
+
+ * EOAttribute+PostgreSQL72.m: added "cardinal_number", "character_data"
+ as known types (v1.0.27)
+
+ * PostgreSQL72Channel+Model.m: code cleanups (v1.0.26)
+
+2004-06-16 Helge Hess <helge.hess@skyrix.com>
+
+ * NSString+PGVal.m, PGConnection.m: fixed some gcc 3.4 warnings
+ (v1.0.25)
+
+2004-06-16 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.24
+
+ * PostgreSQL72Channel: rewrote to use PGResultSet. Removed processing
+ of oid-status which apparently was completely broken before!
+
+ * PGConnection.m: added new PGResultSet object
+
+2004-06-15 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.23
+
+ * PostgreSQL72Channel+Model.m: added -describeDatabaseNames and
+ -describeUserNames methods
+
+ * PostgreSQL72Adaptor.m: minor code cleanups
+
+ * v1.0.22
+
+ * various files: fixed warnings on MacOSX with gstep-make
+
+ * PostgreSQL72Channel.h: rewritten to use PGConnection object
+
+ * started PGConnection object to remove low-level libpq things from
+ the channel (which can then concentrate on implementing the API)
+
+2004-06-06 Helge Hess <helge.hess@opengroupware.org>
+
+ * fixed some MacOSX compilation warnings (v1.0.21)
+
+2004-05-04 Helge Hess <helge.hess@opengroupware.org>
+
+ * GNUmakefile.preamble (PostgreSQL72_BUNDLE_LIBS): added missing libs
+ for current Panther PostgreSQL compilation (v1.0.20)
+
+2004-03-01 Helge Hess <helge.hess@skyrix.com>
+
+ * GNUmakefile.preamble: fixed makefile for "inline" compilation
+ (v1.0.19)
+
+2004-02-12 Helge Hess <helge.hess@opengroupware.org>
+
+ * v1.0.18
+
+ * EOAttribute+PostgreSQL72.m: fixed exception for MacOSX
+
+ * GNUmakefile.preamble: added yet another special case to locate the
+ PostgreSQL header files ...
+
+2004-02-10 Helge Hess <helge.hess@skyrix.com>
+
+ * PostgreSQL72Channel.m: only set client encoding when being compiled
+ with PostgreSQL 7.3+ (seems to have problems with umlauts on Debian
+ 7.2) (v1.0.17)
+
+2004-02-08 Helge Hess <helge.hess@opengroupware.org>
+
+ * PostgreSQL72Channel.m: explicitly set connection encoding to Latin1
+ to avoid problems with databases created as Unicode (v1.0.16)
+
+2004-01-07 Helge Hess <helge.hess@opengroupware.org>
+
+ * PostgreSQL72Exception.m: minor cleanup, include stdarg.h for varargs
+ processing (might fix compilation on Solaris) (v1.0.15)
+
+2004-01-07 Helge Hess <helge.hess@skyrix.com>
+
+ * PostgreSQL72Channel.m: do cache attribute name field indices during
+ invocations, minor performance optimization to fetch method (which
+ requires that the attributes argument is constant!) (v1.0.14)
+
+ * PostgreSQL72Channel.m: raise default value for max-connection count
+ to 50, various cleanups and minor fixes (v1.0.13)
+
+2003-12-26 Helge Hess <helge.hess@opengroupware.org>
+
+ * NSData+PGVal.m ([NSData -stringValueForPostgreSQLType:attribute:]):
+ fixed a bug in the data=>string conversion. Types like
+ "VARCHAR(4000)" where not properly converted, eg a long obj_property
+ value (v1.0.12)
+
+2003-12-13 Helge Hess <helge.hess@opengroupware.org>
+
+ * GNUmakefile.preamble: fixed include flags, so that GDLAccess must not
+ be installed prior compiling the adaptor (v1.0.11)
+
+2003-12-11 Helge Hess <helge.hess@skyrix.com>
+
+ * GNUmakefile (BUNDLE_INSTALL_DIR): install into
+ GNUSTEP_INSTALLATION_DIR instead of GNUSTEP_SYSTEM_ROOT (v1.0.10)
+
+2003-09-03 Helge Hess <helge.hess@skyrix.com>
+
+ * GNUmakefile.preamble: added /usr/include/postgresql as an include
+ search path - this is the position of the headers under Debian
+ (v1.0.9)
+
+2003-07-30 Helge Hess <helge.hess@skyrix.com>
+
+ * NSCalendarDate+PGVal.m: added support for 4 digit timezone offsets
+ (eg +09:30) when parsing PG date values (v1.0.8)
+
+2003-07-28 Helge Hess <helge.hess@skyrix.com>
+
+ * NSCalendarDate+PGVal.m: fixed two more bugs introduced in 1.0.5 ...
+ (v1.0.7)
+
+2003-07-28 Bjoern Stierand <bjoern@opengroupware.org>
+
+ * NSCalendarDate+PGVal.m: fixed release bug introduced in 1.0.5, wrong
+ variable was returned leading to a memory error (v1.0.6)
+
+2003-07-27 Helge Hess <helge.hess@skyrix.com>
+
+ * PostgreSQL72Values.m: split up into separate files, added several
+ performance optimizations to base value creation code (v1.0.5)
+
+2003-07-23 Helge Hess <helge.hess@skyrix.com>
+
+ * more fixes to the include pathes, do not include using <pgsql/xxx.h>
+ but always using <xxx.h> (v1.0.4)
+
+2003-07-21 Helge Hess <helge.hess@skyrix.com>
+
+ * some include cleanups for FreeBSD (reported by Mirko Viviani),
+ fixed some warnings (v1.0.3)
+
+Wed May 14 11:27:21 2003 Jan Reichmann <jan@skyrix.com>
+
+ * PostgreSQL72Values.m: use lowercase type to determine sql type
+ (bug 126) (v1.0.2)
+
+2003-05-07 Helge Hess <helge.hess@skyrix.com>
+
+ * v1.0.1
+
+ * PostgreSQL72Channel.m: small cleanups, speed improvement on attrname
+ creation (used no autorelease pools ...)
+
+ * GNUmakefile (PostgreSQL72_RESOURCE_FILES): added a Version file
+
+Mon May 5 16:27:40 2003 Jan Reichmann <jan@skyrix.com>
+
+ * PostgreSQL72Values.m: implement valueFromCString, valueFromBytes,
+ stringValueForPostgreSQLType for NSData+PostgreSQL72Values (bug 126)
+
+Mon Dec 23 18:20:13 2002 Helge Hess <helge.hess@skyrix.com>
+
+ * ported to MacOSX 10.2.3 (do not use <EOAccess, include common.h)
+
+Tue Nov 26 12:01:49 2002 Jan Reichmann <jan@skyrix.com>
+
+ * EOAttribute+PostgreSQL72.m: add timestamptz type
+
+Tue Nov 5 10:02:45 2002 Jan Reichmann <jan@skyrix.com>
+
+ * PostgreSQLChannel.m: add PGMaxOpenConnectionCount - Default to
+ set the max number of open postgres connections
+
+Fri Oct 18 19:15:15 2002 Jan Reichmann <jan@skyrix.com>
+
+ * EOAttribute+PostgreSQL72.m: add postgres types
+
+Thu Aug 22 11:08:35 2002 Jan Reichmann <jan@skyrix.com>
+
+ * PostgreSQL72Channel.m, PostgreSQL72Values.m:
+ -fixed bug (attributes with the same name were not fetched
+ (both attrs. where set to the first attr.-value)
+ -fixed escape-bug
+
+Thu Jun 13 14:57:10 2002 Jan41 Reichmann <jan@skyrix.com>
+
+ * PostgreSQL72Values.m: remove Logs
+
+Tue Jun 11 14:43:14 2002 Jan41 Reichmann <jan@skyrix.com>
+
+ * PostgreSQL72Context.m: remove abort() :(
+
+Mon Mar 18 12:53:42 CET 2002 Jan41 Reichmann <jan@skyrix.com>
+
+ * PostgreSQLValues.m, *Channel.*: add caches for attributes/
+ add get primary key infos
+
+Mon Mar 11 12:02:24 2002 Jan41 Reichmann <jan@skyrix.com>
+
+ * PostgreSQLValues.m: fixed CAL-FORMAT Entry
+
+Thu Aug 16 14:13:10 2001 Martin Hoerning <mh@skyrix.com>
+
+ * PostgreSQLChannel.m: fixed RETAIN-BUGS, removed LOGS
+
+Fri Jul 27 17:32:17 2001 Jan Reichmann <jan@skyrix.com>
+
+ * EOAttribute+PostgreSQL.m: fixed timezone bugs
+
+Thu Jul 5 14:08:11 2001 Helge Hess <helge.hess@skyrix.com>
+
+ * reactivated for SkyDev41
+
+Tue Feb 2 09:01:10 1999 Helge Hess <helge@trex.mdlink.de>
+
+ * created ChangeLog
--- /dev/null
+/*
+ EOAttribute+PostgreSQL72.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAttribute+PostgreSQL72.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_EOAttribute_H___
+#define ___PostgreSQL72_EOAttribute_H___
+
+#import <GDLAccess/EOAttribute.h>
+#include <libpq-fe.h>
+
+@class NSString;
+
+@interface EOAttribute(PostgreSQL72AttributeAdditions)
+
+- (void)loadValueClassAndTypeUsingPostgreSQLType:(Oid)_type
+ size:(int)_size
+ modification:(int)_modification
+ binary:(BOOL)_isBinary;
+
+- (void)loadValueClassForExternalPostgreSQLType:(NSString *)_type;
+
+@end
+
+#endif /* ___PostgreSQL72_EOAttribute_H___ */
--- /dev/null
+/*
+ EOAttribute+PostgreSQL72.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: EOAttribute+PostgreSQL72.m 1 2004-08-20 10:38:46Z znek $
+
+#include "common.h"
+#import "EOAttribute+PostgreSQL72.h"
+
+#if 0
+#include <pg_type.h>
+#else
+#include <postgres_types.h>
+#endif
+#include <sql3types.h>
+
+// Sybase dateformat: (need to be corrected for PostgreSQL)
+static NSString *PGSQL_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p";
+static NSString *PGSQL_TIMESTAMP_FORMAT = @"%Y-%m-%d %H:%M:%S%z";
+
+@implementation EOAttribute(PostgreSQL72AttributeAdditions)
+
+- (void)loadValueClassAndTypeUsingPostgreSQLType:(Oid)_type
+ size:(int)_size
+ modification:(int)_modification
+ binary:(BOOL)_isBinary
+{
+ if (_isBinary)
+ [self setValueClassName:@"NSData"];
+
+ switch (_type) {
+ /* where in the PostgreSQL72 headers are these OIDs defined ??? */
+ case BOOLOID:
+ [self setExternalType:@"bool"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ return;
+ case NAMEOID:
+ [self setExternalType:@"name"];
+ [self setValueClassName:@"NSString"];
+ return;
+ case TEXTOID:
+ [self setExternalType:@"textoid"];
+ [self setValueClassName:@"NSString"];
+ return;
+ case INT2OID:
+ [self setExternalType:@"int2"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ return;
+ case INT4OID:
+ [self setExternalType:@"int4"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ return;
+ case INT8OID:
+ [self setExternalType:@"int8"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ return;
+
+ case CHAROID:
+ [self setExternalType:@"char"];
+ [self setValueClassName:@"NSString"];
+ break;
+ case VARCHAROID:
+ [self setExternalType:@"varchar"];
+ [self setValueClassName:@"NSString"];
+ break;
+ case NUMERICOID:
+ [self setExternalType:@"numeric"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ break;
+ case FLOAT4OID:
+ [self setExternalType:@"float4"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"f"];
+ break;
+ case FLOAT8OID:
+ [self setExternalType:@"float8"];
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"f"];
+ break;
+
+ case DATEOID:
+ [self setExternalType:@"datetime"];
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_DATETIME_FORMAT];
+ break;
+ case TIMEOID:
+ [self setExternalType:@"time"];
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_DATETIME_FORMAT];
+ break;
+ case TIMESTAMPOID:
+ [self setExternalType:@"timestamp"];
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_DATETIME_FORMAT];
+ break;
+ case TIMESTAMPTZOID:
+ [self setExternalType:@"timestamptz"];
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_DATETIME_FORMAT];
+ break;
+ case BITOID:
+ [self setExternalType:@"bit"];
+ break;
+ default:
+ NSLog(@"What is PGSQL Oid %i ???", _type);
+ break;
+ }
+}
+
+- (void)loadValueClassForExternalPostgreSQLType:(NSString *)_type {
+ if ([_type isEqualToString:@"bool"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ }
+ else if ([_type isEqualToString:@"int2"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ }
+ else if ([_type isEqualToString:@"int4"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"i"];
+ }
+ else if ([_type isEqualToString:@"float4"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"f"];
+ }
+ else if ([_type isEqualToString:@"float8"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ }
+ else if ([_type isEqualToString:@"decimal"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ }
+ else if ([_type isEqualToString:@"numeric"]) {
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ }
+ else if ([_type isEqualToString:@"cardinal_number"]) {
+ // TODO: not sure whether this is correct (comes from sql_features table)
+ [self setValueClassName:@"NSNumber"];
+ [self setValueType:@"d"];
+ }
+ else if ([_type isEqualToString:@"name"]) {
+ [self setExternalType:@"name"];
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"varchar"]) {
+ [self setExternalType:@"varchar"];
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"char"]) {
+ [self setExternalType:@"char"];
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"character_data"]) {
+ // TODO: not sure whether this is correct (comes from sql_features table)
+ [self setExternalType:@"character_data"];
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"timestamp"]) {
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_TIMESTAMP_FORMAT];
+ }
+ else if ([_type isEqualToString:@"timestamptz"]) {
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_TIMESTAMP_FORMAT];
+ }
+ else if ([_type isEqualToString:@"datetime"]) {
+ [self setValueClassName:@"NSCalendarDate"];
+ [self setCalendarFormat:PGSQL_DATETIME_FORMAT];
+ }
+ else if ([_type isEqualToString:@"date"]) {
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"time"]) {
+ [self setValueClassName:@"NSString"];
+ }
+ else if ([_type isEqualToString:@"text"]) {
+ [self setValueClassName:@"NSString"];
+ }
+ else {
+ NSLog(@"%s: invalid argument %@", __PRETTY_FUNCTION__, _type);
+
+#if LIB_FOUNDATION_LIBRARY
+ [InvalidArgumentException raise:@"InvalidArgumentException"
+ format:
+ @"invalid PostgreSQL72 type %@ passed to "
+ @"-loadValueClassForExternalPostgreSQLType:",
+ _type];
+#else
+ [NSException raise:@"InvalidArgumentException"
+ format:
+ @"invalid PostgreSQL72 type %@ passed to "
+ @"-loadValueClassForExternalPostgreSQLType:",
+ _type];
+#endif
+ }
+}
+
+@end /* EOAttribute(PostgreSQL72) */
+
+void __link_EOAttributePostgreSQL72() {
+ // used to force linking of object file
+ __link_EOAttributePostgreSQL72();
+}
--- /dev/null
+#
+# GNUmakefile
+#
+# Copyright (C) 2004 SKYRIX Software AG
+#
+# Author: Helge Hess (helge.hess@skyrix.com)
+#
+# This file is part of the PostgreSQL Adaptor Library
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; see the file COPYING.LIB.
+# If not, write to the Free Software Foundation,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# $Id: GNUmakefile 1 2004-08-20 10:38:46Z znek $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+BUNDLE_NAME = PostgreSQL72
+
+PostgreSQL72_OBJC_FILES = \
+ PGConnection.m \
+ PostgreSQL72Expression.m \
+ PostgreSQL72Adaptor.m \
+ PostgreSQL72Context.m \
+ PostgreSQL72Channel.m \
+ PostgreSQL72Channel+Model.m \
+ PostgreSQL72Exception.m \
+ PostgreSQL72Values.m \
+ NSString+PostgreSQL72.m \
+ EOAttribute+PostgreSQL72.m \
+ NSString+PGVal.m \
+ NSData+PGVal.m \
+ NSCalendarDate+PGVal.m \
+ NSNumber+PGVal.m \
+
+PostgreSQL72_PRINCIPAL_CLASS = PostgreSQL72Adaptor
+
+BUNDLE_INSTALL = PostgreSQL72
+BUNDLE_INSTALL_DIR = $(GNUSTEP_INSTALLATION_DIR)/Libraries/Adaptors
+
+# Use .gdladaptor as the bundle extension
+BUNDLE_EXTENSION = .gdladaptor
+
+PostgreSQL72_RESOURCE_FILES += Version
+
+# tool
+
+TOOL_NAME = gdltest
+
+gdltest_OBJC_FILES = gdltest.m
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/bundle.make
+#include $(GNUSTEP_MAKEFILES)/tool.make
+-include GNUmakefile.postamble
--- /dev/null
+#
+# GNUmakefile
+#
+# Copyright (C) 2003-2004 SKYRIX Software AG
+#
+# Author: Helge Hess (helge.hess@skyrix.com)
+#
+# This file is part of the PostgreSQL Adaptor Library
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; see the file COPYING.LIB.
+# If not, write to the Free Software Foundation,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# $Id: GNUmakefile.preamble 1 2004-08-20 10:38:46Z znek $
+
+PostgreSQL72_BUNDLE_LIBS += -lpq
+PostgreSQL72_BUNDLE_LIBS += -lGDLAccess -lEOControl
+
+gdltest_TOOL_LIBS += -lGDLAccess
+
+# set compile flags and go
+
+ADDITIONAL_INCLUDE_DIRS += \
+ -I../GDLAccess -I..
+
+ADDITIONAL_INCLUDE_DIRS += \
+ -I$(PGSQL)/include/pgsql \
+ -I$(PGSQL)/include \
+ -I.. -I../.. \
+ -I../../../SOPE/skyrix-core/ \
+ -I/usr/local/include/pgsql \
+ -I/usr/local/include \
+ -I/usr/local/pgsql/include \
+ -I/usr/include/pgsql \
+ -I/usr/include/postgresql \
+ -I/usr/include \
+ -I/Library/PostgreSQL/include/ \
+
+ADDITIONAL_LIB_DIRS += \
+ -L../GDLAccess/$(GNUSTEP_OBJ_DIR)\
+ -L$(PGSQL)/lib \
+ -L/usr/local/lib \
+ -L/usr/local/pgsql/lib/ \
+ -L/usr/lib
+
+ifeq ($(FOUNDATION_LIB),apple)
+
+PostgreSQL72_BUNDLE_LIBS += -lssl -lcrypto
+
+endif
--- /dev/null
+// $Id: NSCalendarDate+PGVal.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/NSString.h>
+#include "PostgreSQL72Channel.h"
+#include "common.h"
+
+// Sybase Date: Oct 21 1997 9:52:26:000PM
+static NSString *PGSQL_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p";
+
+@implementation NSCalendarDate(PostgreSQL72Values)
+
+/*
+ Format: '2001-07-26 14:00:00+02' (len 22)
+ '2001-07-26 14:00:00+09:30' (len 25)
+ 0123456789012345678901234
+
+ Matthew: "07/25/2003 06:00:00 CDT".
+*/
+
+static Class NSCalDateClass = Nil;
+static NSTimeZone *DefServerTimezone = nil;
+static NSTimeZone *gmt = nil;
+static NSTimeZone *gmt01 = nil;
+static NSTimeZone *gmt02 = nil;
+
++ (id)valueFromCString:(const char *)_cstr length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+ static unsigned char buf[28]; // reused buffer
+ unsigned char *p;
+ NSTimeZone *attrTZ;
+ NSCalendarDate *date;
+ int year, month, day, hour, min, sec, tzOffset = 0;
+
+ if (_length == 0)
+ return nil;
+
+ if (_length != 22 && _length != 25) {
+ // TODO: add support for "2001-07-26 14:00:00" (len=19)
+ NSLog(@"ERROR(%s): unexpected string '%s' for date type '%@', returning "
+ @"now (expected format: '2001-07-26 14:00:00+02')",
+ __PRETTY_FUNCTION__,
+ _cstr, _type);
+ return [NSCalendarDate date];
+ }
+ strncpy(buf, _cstr, 25);
+ buf[25] = '\0';
+
+ /* perform on reverse, so that we don't overwrite with null-terminators */
+
+ if (_length == 22) {
+ p = &(buf[19]);
+ tzOffset = atoi(p) * 60;
+ }
+ else if (_length >= 25) {
+ int mins;
+ p = &(buf[23]);
+ mins = atoi(p);
+ buf[22] = '\0'; // the ':'
+ p = &(buf[19]);
+ tzOffset = atoi(p) * 60;
+ tzOffset = tzOffset > 0 ? (tzOffset + mins) : (tzOffset - mins);
+ }
+
+ p = &(buf[17]); buf[19] = '\0'; sec = atoi(p);
+ p = &(buf[14]); buf[16] = '\0'; min = atoi(p);
+ p = &(buf[11]); buf[13] = '\0'; hour = atoi(p);
+ p = &(buf[8]); buf[10] = '\0'; day = atoi(p);
+ p = &(buf[5]); buf[7] = '\0'; month = atoi(p);
+ p = &(buf[0]); buf[4] = '\0'; year = atoi(p);
+
+ /* TODO: cache all timezones (just 26 ;-) */
+ switch (tzOffset) {
+ case 0:
+ if (gmt == nil) {
+ gmt = [[NSTimeZone timeZoneForSecondsFromGMT:0] retain];
+ NSAssert(gmt, @"could not create GMT timezone?!");
+ }
+ attrTZ = gmt;
+ break;
+ case 60:
+ if (gmt01 == nil) {
+ gmt01 = [[NSTimeZone timeZoneForSecondsFromGMT:3600] retain];
+ NSAssert(gmt01, @"could not create GMT+01 timezone?!");
+ }
+ attrTZ = gmt01;
+ break;
+ case 120:
+ if (gmt02 == nil) {
+ gmt02 = [[NSTimeZone timeZoneForSecondsFromGMT:7200] retain];
+ NSAssert(gmt02, @"could not create GMT+02 timezone?!");
+ }
+ attrTZ = gmt02;
+ break;
+
+ default: {
+ /* cache the first, "alternative" timezone */
+ static int firstTZOffset = 0; // can use 0 since GMT is a separate case
+ static NSTimeZone *firstTZ = nil;
+ if (firstTZOffset == 0) {
+ firstTZOffset = tzOffset;
+ firstTZ = [[NSTimeZone timeZoneForSecondsFromGMT:(tzOffset*60)] retain];
+ }
+
+ attrTZ = (firstTZOffset == tzOffset)
+ ? firstTZ
+ : [NSTimeZone timeZoneForSecondsFromGMT:(tzOffset * 60)];
+ break;
+ }
+ }
+
+ if (NSCalDateClass == Nil) NSCalDateClass = [[NSCalendarDate class] retain];
+ date = [NSCalDateClass dateWithYear:year month:month day:day
+ hour:hour minute:min second:sec
+ timeZone:attrTZ];
+ if (date == nil) {
+ NSLog(@"ERROR(%s): could not construct date from string '%s': "
+ @"year=%i,month=%i,day=%i,hour=%i,minute=%i,second=%i, tz=%@",
+ __PRETTY_FUNCTION__, _cstr,
+ year, month, day, hour, min, sec, attrTZ);
+ }
+ return date;
+}
+
++ (id)valueFromBytes:(const void *)_bytes length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+#if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
+ NSLog(@"%s: not implemented!", __PRETTY_FUNCTION__);
+ return nil;
+#else
+ return [self notImplemented:_cmd];
+#endif
+}
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+{
+#if 0
+ NSString *format;
+#endif
+ EOQuotedExpression *expr;
+ NSTimeZone *serverTimeZone;
+ NSString *format;
+ NSString *val;
+
+ if ((serverTimeZone = [_attribute serverTimeZone]) == nil ) {
+ if (DefServerTimezone == nil) {
+ DefServerTimezone = [[NSTimeZone localTimeZone] retain];
+ NSLog(@"Note: PostgreSQL72 adaptor using timezone '%@' as default",
+ DefServerTimezone);
+ }
+ serverTimeZone = DefServerTimezone;
+ }
+
+#if 0
+ format = [_attribute calendarFormat];
+#else /* hm, why is that? */
+ format = @"%Y-%m-%d %H:%M:%S%z";
+#endif
+ if (format == nil)
+ format = PGSQL_DATETIME_FORMAT;
+
+ [self setTimeZone:serverTimeZone];
+
+ val = [self descriptionWithCalendarFormat:format];
+ expr = [[EOQuotedExpression alloc] initWithExpression:val
+ quote:@"\'" escape:@"\\'"];
+ val = [[expr expressionValueForContext:nil] retain];
+ [expr release];
+
+ return [val autorelease];
+}
+
+@end /* NSCalendarDate(PostgreSQL72Values) */
--- /dev/null
+// $Id: NSData+PGVal.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/NSData.h>
+#include "PostgreSQL72Values.h"
+#include "PostgreSQL72Channel.h"
+#include "common.h"
+
+@implementation NSData(PostgreSQL72Values)
+
+static BOOL doDebug = NO;
+static NSData *EmptyData = nil;
+
++ (id)valueFromCString:(const char *)_cstr length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+ if (_length == 0) {
+ if (EmptyData == nil) EmptyData = [[NSData alloc] init];
+ return EmptyData;
+ }
+ return [[[self alloc] initWithBytes:_cstr length:_length] autorelease];
+}
+
++ (id)valueFromBytes:(const void *)_bytes length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+ if (_length == 0) {
+ if (EmptyData == nil) EmptyData = [[NSData alloc] init];
+ return EmptyData;
+ }
+ return [[[self alloc] initWithBytes:_bytes length:_length] autorelease];
+}
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+{
+ // TODO: UNICODE
+ // TODO: this method looks slow
+ // example type: "VARCHAR(4000)"
+ static NSStringEncoding enc = 0;
+ NSString *str, *t;
+ unsigned len;
+ unichar c1;
+
+ if ((len = [self length]) == 0)
+ return @"";
+
+ if (enc == 0) {
+ enc = [NSString defaultCStringEncoding];
+ NSLog(@"Note: PostgreSQL72 adaptor using '%@' encoding for data=>string "
+ @"conversion.",
+ [NSString localizedNameOfStringEncoding:enc]);
+ }
+
+ str = [[NSString alloc] initWithData:self encoding:enc];
+
+ if (doDebug) {
+ NSLog(@"Note: made string (len=%i) for data (len=%i), type %@",
+ [str length], [self length], _type);
+ }
+
+ if ((len = [_type length]) == 0) {
+ NSLog(@"WARNING(%s): missing type for data=>string conversion!",
+ __PRETTY_FUNCTION__);
+ return [str autorelease];
+ }
+
+ c1 = [_type characterAtIndex:0];
+ switch (c1) {
+ case 'c': case 'C': // char
+ case 'v': case 'V': // varchar
+ case 'm': case 'M': // money
+ case 't': case 'T': // text
+ t = [_type lowercaseString];
+ if ([t hasPrefix:@"char"] ||
+ [t hasPrefix:@"varchar"] ||
+ [t hasPrefix:@"money"] ||
+ [t hasPrefix:@"text"]) {
+ if (doDebug) NSLog(@" converting type: %@", t);
+ t = [[str stringValueForPostgreSQLType:_type
+ attribute:_attribute] copy];
+ [str release];
+ if (doDebug) NSLog(@" result len %i", [t length]);
+ return [t autorelease];
+ }
+ }
+
+ NSLog(@"WARNING(%s): no processing of type '%@' for "
+ @"data=>string conversion!",
+ __PRETTY_FUNCTION__, _type);
+ return [str autorelease];;
+}
+
+@end /* NSData(PostgreSQL72Values) */
--- /dev/null
+// $Id: NSNumber+PGVal.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/NSString.h>
+#include "PostgreSQL72Channel.h"
+#include "common.h"
+
+@implementation NSNumber(PostgreSQL72Values)
+
+static BOOL debugOn = NO;
+static Class NSNumberClass = Nil;
+static NSNumber *yesNum = nil;
+static NSNumber *noNum = nil;
+
++ (id)valueFromCString:(const char *)_cstr length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+ // TODO: can we avoid the lowercaseString?
+ unsigned len;
+ unichar c1;
+
+ if ((len = [_type length]) == 0)
+ return nil;
+
+ if (NSNumberClass == Nil) NSNumberClass = [NSNumber class];
+
+ c1 = [_type characterAtIndex:0];
+ switch (c1) {
+ case 'f': case 'F': {
+ if (len < 5)
+ break;
+ if ([[_type lowercaseString] hasPrefix:@"float"])
+ return [NSNumberClass numberWithDouble:atof(_cstr)];
+ break;
+ }
+ case 's': case 'S': {
+ if (len < 8)
+ break;
+ if ([[_type lowercaseString] hasPrefix:@"smallint"])
+ return [NSNumberClass numberWithShort:atoi(_cstr)];
+ break;
+ }
+ case 'i': case 'I': {
+ if (len < 3)
+ break;
+ if ([[_type lowercaseString] hasPrefix:@"int"])
+ return [NSNumberClass numberWithInt:atoi(_cstr)];
+ }
+ case 'b': case 'B': {
+ if (len < 4)
+ break;
+ if (![[_type lowercaseString] hasPrefix:@"bool"])
+ break;
+
+ if (yesNum == nil) yesNum = [[NSNumberClass numberWithBool:YES] retain];
+ if (noNum == nil) noNum = [[NSNumberClass numberWithBool:NO] retain];
+
+ if (_length == 0)
+ return noNum;
+
+ switch (*_cstr) {
+ case 't': case 'T':
+ case 'y': case 'Y':
+ case '1':
+ return yesNum;
+ default:
+ return noNum;
+ }
+ }
+ }
+ return nil;
+}
+
++ (id)valueFromBytes:(const void *)_bytes length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+#if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
+ NSLog(@"%s: not implemented!", __PRETTY_FUNCTION__);
+ return nil;
+#else
+ return [self notImplemented:_cmd];
+#endif
+}
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+{
+ // TODO: can we avoid the lowercaseString?
+ unsigned len;
+ unichar c1;
+
+ if (debugOn)
+ NSLog(@"%s(type=%@,attr=%@)", __PRETTY_FUNCTION__, _type, _attribute);
+
+ if ((len = [_type length]) == 0) {
+ if (debugOn) NSLog(@" no type, return string");
+ return [self stringValue];
+ }
+ if (len < 4) { /* apparently this is 'INT'? */
+ if (debugOn) NSLog(@" type len < 4 (%@), return string", _type);
+#if GNUSTEP_BASE_LIBRARY
+ /*
+ on gstep-base -stringValue of bool's return YES or NO, which seems to
+ be different on Cocoa and liBFoundation.
+ */
+ {
+ Class BoolClass = Nil;
+
+ if (BoolClass == Nil) BoolClass = NSClassFromString(@"NSBoolNumber");
+ if ([self isKindOfClass:BoolClass])
+ return [self boolValue] ? @"1" : @"0";
+ }
+#endif
+ return [self stringValue];
+ }
+
+ c1 = [_type characterAtIndex:0];
+ if (debugOn) NSLog(@" typecode '%c' ...", c1);
+ switch (c1) {
+ case 'b': case 'B':
+ if (![[_type lowercaseString] hasPrefix:@"bool"])
+ break;
+ return [self boolValue] ? @"true" : @"false";
+
+ case 'm': case 'M': {
+ if (![[_type lowercaseString] hasPrefix:@"money"])
+ break;
+ return [@"$" stringByAppendingString:[self stringValue]];
+ }
+
+ case 'c': case 'C':
+ case 't': case 'T':
+ case 'v': case 'V': {
+ static NSMutableString *ms = nil; // reuse mstring, THREAD
+
+ _type = [_type lowercaseString];
+ if (!([_type hasPrefix:@"char"] ||
+ [_type hasPrefix:@"varchar"] ||
+ [_type hasPrefix:@"text"]))
+ break;
+
+ // TODO: can we get this faster?!
+ if (ms == nil) ms = [[NSMutableString alloc] initWithCapacity:256];
+ [ms setString:@"'"];
+ [ms appendString:[self stringValue]];
+ [ms appendString:@"'"];
+ return [[ms copy] autorelease];
+ }
+ }
+ return [self stringValue];
+}
+
+@end /* NSNumber(PostgreSQL72Values) */
--- /dev/null
+// $Id: NSString+PGVal.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/NSString.h>
+#include "PostgreSQL72Channel.h"
+#include <NGExtensions/NSString+Ext.h>
+#include "common.h"
+
+@implementation NSString(PostgreSQL72Values)
+
+static Class NSStringClass = Nil;
+static Class EOExprClass = Nil;
+
++ (id)valueFromCString:(const char *)_cstr length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+ if (_cstr == NULL) return nil;
+ if (*_cstr == '\0') return @"";
+ if (NSStringClass == Nil) NSStringClass = [NSString class];
+
+ // TODO: cache IMP of selector
+ return [NSStringClass stringWithCString:_cstr];
+}
+
++ (id)valueFromBytes:(const void *)_bytes length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel
+{
+#if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
+ NSLog(@"%s: not implemented!", __PRETTY_FUNCTION__);
+ return nil;
+#else
+ return [self notImplemented:_cmd];
+#endif
+}
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+{
+ // TODO: all this looks slow ...
+ unsigned len;
+ unichar c1;
+
+ if ((len = [_type length]) == 0)
+ return self;
+
+ c1 = [_type characterAtIndex:0];
+ switch (c1) {
+ case 'c': case 'C':
+ case 'v': case 'V':
+ case 't': case 'T': {
+ NSString *s;
+ EOQuotedExpression *expr;
+
+ if (len < 4)
+ return self;
+
+ _type = [_type lowercaseString];
+
+ if (!([_type hasPrefix:@"char"] ||
+ [_type hasPrefix:@"varchar"] ||
+ [_type hasPrefix:@"text"]))
+ break;
+
+ /* TODO: creates too many autoreleased strings :-( */
+
+ s = [self stringByReplacingString:@"\\" withString:@"\\\\"];
+
+ if (EOExprClass == Nil) EOExprClass = [EOQuotedExpression class];
+ expr = [[EOExprClass alloc] initWithExpression:s quote:@"'" escape:@"\\'"];
+ s = [[expr expressionValueForContext:nil] retain];
+ [expr release];
+ return [s autorelease];
+ }
+ case 'm': case 'M': {
+ if (len < 5) {
+ if ([[_type lowercaseString] hasPrefix:@"money"])
+ return [@"$" stringByAppendingString:self];
+ }
+ break;
+ }
+ }
+ return self;
+}
+
+@end /* NSString(PostgreSQL72Values) */
--- /dev/null
+/*
+ NSString+PostgreSQL72.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: NSString+PostgreSQL72.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_NSString_H___
+#define ___PostgreSQL72_NSString_H___
+
+#import <Foundation/NSString.h>
+
+@interface NSString(PostgreSQL72MiscStrings)
+
+- (NSString *)_pgModelMakeInstanceVarName;
+- (NSString *)_pgModelMakeClassName;
+- (NSString *)_pgStringWithCapitalizedFirstChar;
+- (NSString *)_pgStripEndSpaces;
+
+@end
+
+#endif
--- /dev/null
+/*
+ NSString+PostgreSQL72.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: NSString+PostgreSQL72.m 1 2004-08-20 10:38:46Z znek $
+
+#if LIB_FOUNDATION_BOEHM_GC
+# include <objc/gc.h>
+#endif
+
+#import <objc/objc-api.h>
+#include "common.h"
+#import "NSString+PostgreSQL72.h"
+
+@implementation NSString(PostgreSQL72MiscStrings)
+
+- (NSString *)_pgModelMakeInstanceVarName {
+ if ([self length] == 0)
+ return @"";
+ else {
+ unsigned clen = 0;
+ char *s = NULL;
+ int cnt, cnt2;
+
+ clen = [self cStringLength];
+ s = malloc(clen + 10);
+
+ [self getCString:s maxLength:clen];
+
+ for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) {
+ if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = toupper(s[cnt + 1]);
+ cnt++;
+ }
+ else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = s[cnt];
+ cnt++;
+ cnt2++;
+ s[cnt2] = toupper(s[cnt]);
+ }
+ else
+ s[cnt2] = tolower(s[cnt]);
+ }
+ s[cnt2] = '\0';
+
+ return [[[NSString alloc]
+ initWithCStringNoCopy:s length:strlen(s) freeWhenDone:YES]
+ autorelease];
+ }
+}
+
+- (NSString *)_pgModelMakeClassName {
+ if ([self length] == 0)
+ return @"";
+ else {
+ unsigned clen = 0;
+ char *s = NULL;
+ int cnt, cnt2;
+
+ clen = [self cStringLength];
+ s = malloc(clen + 10);
+
+ [self getCString:s maxLength:clen];
+
+ for (cnt = cnt2 = 0; cnt < clen; cnt++, cnt2++) {
+ if ((s[cnt] == '_') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = toupper(s[cnt + 1]);
+ cnt++;
+ }
+ else if ((s[cnt] == '2') && (s[cnt + 1] != '\0')) {
+ s[cnt2] = s[cnt];
+ cnt++;
+ cnt2++;
+ s[cnt2] = toupper(s[cnt]);
+ }
+ else
+ s[cnt2] = tolower(s[cnt]);
+ }
+ s[cnt2] = '\0';
+
+ s[0] = toupper(s[0]);
+
+ return [[[NSString alloc]
+ initWithCStringNoCopy:s length:strlen(s)
+ freeWhenDone:YES]
+ autorelease];
+ }
+}
+
+- (NSString *)_pgStringWithCapitalizedFirstChar {
+ NSCharacterSet *upperSet = [NSCharacterSet uppercaseLetterCharacterSet];
+
+ if ([self length] == 0)
+ return @"";
+ else if ([upperSet characterIsMember:[self characterAtIndex:0]])
+ return [[self copy] autorelease];
+ else {
+ NSMutableString *str = [NSMutableString stringWithCapacity:[self length]];
+
+ [str appendString:[[self substringToIndex:1] uppercaseString]];
+ [str appendString:[self substringFromIndex:1]];
+
+ return [[str copy] autorelease];
+ }
+}
+
+- (NSString *)_pgStripEndSpaces {
+ if ([self length] > 0) {
+ NSCharacterSet *spaceSet = [NSCharacterSet whitespaceCharacterSet];
+ NSMutableString *str = [NSMutableString stringWithCapacity:[self length]];
+ IMP charAtIndex;
+ NSRange range;
+
+ charAtIndex = [self methodForSelector:@selector(characterAtIndex:)];
+ range.length = 0;
+
+ for (range.location = ([self length] - 1);
+ range.location >= 0;
+ range.location++, range.length++) {
+ unichar c;
+
+ c = (unichar)(int)charAtIndex(self, @selector(characterAtIndex:),
+ range.location);
+ if (![spaceSet characterIsMember:c])
+ break;
+ }
+
+ if (range.length > 0) {
+ [str appendString:self];
+ [str deleteCharactersInRange:range];
+ return AUTORELEASE([str copy]);
+ }
+ }
+ return AUTORELEASE([self copy]);
+}
+
+@end
+
+void __link_NSStringPostgreSQL72() {
+ // used to force linking of object file
+ __link_NSStringPostgreSQL72();
+}
--- /dev/null
+/*
+ PGConnection.h
+
+ Copyright (C) 2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PGConnection.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_PGConnection_H___
+#define ___PostgreSQL72_PGConnection_H___
+
+#import <Foundation/NSObject.h>
+
+@class NSString, NSException;
+@class PGResultSet;
+
+@interface PGConnection : NSObject
+{
+@public
+ void *_connection;
+}
+
+- (id)initWithHostName:(NSString *)_host port:(NSString *)_port
+ options:(NSString *)_options tty:(NSString *)_tty
+ database:(NSString *)_dbname
+ login:(NSString *)_login password:(NSString *)_pwd;
+
+/* accessors */
+
+- (BOOL)isValid;
+
+/* connect operations */
+
+- (NSException *)startConnectWithInfo:(NSString *)_conninfo; // async
+
+- (NSException *)connectWithInfo:(NSString *)_conninfo;
+- (NSException *)connectWithHostName:(NSString *)_host port:(NSString *)_port
+ options:(NSString *)_options tty:(NSString *)_tty
+ database:(NSString *)_dbname
+ login:(NSString *)_login password:(NSString *)_pwd;
+
+- (void)finish;
+
+- (BOOL)isConnectionOK;
+
+/* message callbacks */
+
+- (BOOL)setNoticeProcessor:(void *)_callback context:(void *)_ctx;
+
+/* settings */
+
+- (BOOL)setClientEncoding:(NSString *)_encoding;
+
+/* errors */
+
+- (NSString *)errorMessage;
+
+/* queries */
+
+- (void *)rawExecute:(NSString *)_sql;
+- (void)clearRawResults:(void *)_ptr;
+- (PGResultSet *)execute:(NSString *)_sql;
+
+@end
+
+@interface PGResultSet : NSObject
+{
+@protected
+ PGConnection *connection;
+@public
+ void *results;
+}
+
+- (id)initWithConnection:(PGConnection *)_con handle:(void *)_handle;
+
+/* accessors */
+
+- (BOOL)isValid;
+
+- (BOOL)containsBinaryTuples;
+- (NSString *)commandStatus;
+- (NSString *)commandTuples;
+
+/* fields */
+
+- (unsigned)fieldCount;
+- (NSString *)fieldNameAtIndex:(unsigned int)_idx;
+- (int)indexOfFieldNamed:(NSString *)_name;
+- (int)fieldSizeAtIndex:(unsigned int)_idx;
+- (int)modifierAtIndex:(unsigned int)_idx;
+
+/* tuples */
+
+- (unsigned int)tupleCount;
+- (BOOL)isNullTuple:(int)_tuple atIndex:(unsigned int)_idx;
+- (void *)rawValueOfTuple:(int)_tuple atIndex:(unsigned int)_idx;
+- (int)lengthOfTuple:(int)_tuple atIndex:(unsigned int)_idx;
+
+/* operations */
+
+- (void)clear;
+
+@end
+
+#endif /* ___PostgreSQL72_PGConnection_H___ */
--- /dev/null
+/*
+ PGConnection.m
+
+ Copyright (C) 2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PGConnection.m 1 2004-08-20 10:38:46Z znek $
+
+#include "PGConnection.h"
+#include "common.h"
+#include <libpq-fe.h>
+
+#if PG_MAJOR_VERSION >= 6 && PG_MINOR_VERSION > 3
+# define NG_HAS_NOTICE_PROCESSOR 1
+# define NG_HAS_BINARY_TUPLES 1
+# define NG_HAS_FMOD 1
+#endif
+
+#if PG_MAJOR_VERSION >= 7 && PG_MINOR_VERSION > 3
+# define NG_SET_CLIENT_ENCODING 1
+#endif
+
+@implementation PGConnection
+
+static BOOL debugOn = NO;
+
+- (id)initWithHostName:(NSString *)_host port:(NSString *)_port
+ options:(NSString *)_options tty:(NSString *)_tty
+ database:(NSString *)_dbname
+ login:(NSString *)_login password:(NSString *)_pwd
+{
+ if ((self = [self init])) {
+ NSException *error;
+
+ error = [self connectWithHostName:_host port:_port options:_options
+ tty:_tty database:_dbname login:_login password:_pwd];
+ if (error != nil) {
+ if (debugOn)
+ NSLog(@"%s: could not connect: %@", __PRETTY_FUNCTION__, error);
+ [self release];
+ return nil;
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self finish];
+ [super dealloc];
+}
+
+/* support */
+
+- (const char *)_cstrFromString:(NSString *)_s {
+ // TODO: fix API, check what the API string encoding is
+ return [_s cString];
+}
+- (NSString *)_stringFromCString:(const char *)_cstr {
+ return [NSString stringWithCString:_cstr];
+}
+
+/* accessors */
+
+- (BOOL)isValid {
+ return self->_connection != NULL ? YES : NO;
+}
+
+/* errors */
+
+- (NSException *)_makeConnectException:(const char *)_func {
+ return [NSException exceptionWithName:@"PGConnectFailed"
+ reason:[NSString stringWithCString:_func]
+ userInfo:nil];
+}
+
+/* connect operations */
+
+- (void)_disconnect {
+ if (self->_connection != NULL)
+ [self finish];
+}
+
+- (NSException *)startConnectWithInfo:(NSString *)_conninfo {
+ [self _disconnect];
+
+ self->_connection = PQconnectStart([self _cstrFromString:_conninfo]);
+ if (self->_connection == NULL)
+ return [self _makeConnectException:__PRETTY_FUNCTION__];
+ return nil;
+}
+// TODO: add method for polling connect status
+
+- (NSException *)connectWithInfo:(NSString *)_conninfo {
+ [self _disconnect];
+
+ self->_connection = PQconnectdb([self _cstrFromString:_conninfo]);
+ if (self->_connection == NULL)
+ return [self _makeConnectException:__PRETTY_FUNCTION__];
+ return nil;
+}
+
+- (NSException *)connectWithHostName:(NSString *)_host port:(NSString *)_port
+ options:(NSString *)_options tty:(NSString *)_tty
+ database:(NSString *)_dbname
+ login:(NSString *)_login password:(NSString *)_pwd
+{
+ [self _disconnect];
+
+ self->_connection = PQsetdbLogin([self _cstrFromString:_host],
+ [self _cstrFromString:_port],
+ [self _cstrFromString:_options],
+ [self _cstrFromString:_tty],
+ [self _cstrFromString:_dbname],
+ [self _cstrFromString:_login],
+ [self _cstrFromString:_pwd]);
+ if (self->_connection == NULL)
+ return [self _makeConnectException:__PRETTY_FUNCTION__];
+ return nil;
+}
+
+- (void)finish {
+ if (self->_connection != NULL) {
+ PQfinish(self->_connection);
+ self->_connection = NULL;
+ }
+}
+
+- (BOOL)isConnectionOK {
+ if (![self isValid])
+ return NO;
+ return PQstatus(self->_connection) == CONNECTION_OK ? YES : NO;
+}
+
+/* message callbacks */
+
+- (BOOL)setNoticeProcessor:(void *)_callback context:(void *)_ctx {
+#if NG_HAS_NOTICE_PROCESSOR
+ PQsetNoticeProcessor(self->_connection, _callback, _ctx);
+ return YES; // TODO: improve error handling
+#else
+ return NO;
+#endif
+}
+
+/* settings */
+
+- (BOOL)setClientEncoding:(NSString *)_encoding {
+ return PQsetClientEncoding(self->_connection,
+ [self _cstrFromString:_encoding]) == 0 ? YES : NO;
+}
+
+/* errors */
+
+- (NSString *)errorMessage {
+ if (![self isValid])
+ return nil;
+
+ return [self _stringFromCString:PQerrorMessage(self->_connection)];
+}
+
+/* queries */
+
+- (void *)rawExecute:(NSString *)_sql {
+ return PQexec(self->_connection, [self _cstrFromString:_sql]);
+}
+- (void)clearRawResults:(void *)_ptr {
+ if (_ptr == NULL) return;
+ PQclear(_ptr);
+}
+
+- (PGResultSet *)execute:(NSString *)_sql {
+ void *handle;
+
+ if ((handle = [self rawExecute:_sql]) == NULL)
+ return nil;
+
+ return [[[PGResultSet alloc] initWithConnection:self handle:handle]
+ autorelease];
+}
+
+/* debugging */
+
+- (BOOL)isDebuggingEnabled {
+ return debugOn;
+}
+
+/* description */
+
+- (NSString *)description {
+ NSMutableString *ms;
+
+ ms = [NSMutableString stringWithCapacity:128];
+ [ms appendFormat:@"<0x%08X[%@]: ", self, NSStringFromClass([self class])];
+ if ([self isValid])
+ [ms appendFormat:@" connection=0x%08X", self->_connection];
+ else
+ [ms appendString:@" not-connected"];
+ [ms appendString:@">"];
+ return ms;
+}
+
+@end /* PGConnection */
+
+@implementation PGResultSet
+
+/* wraps PGresult */
+
+- (id)initWithConnection:(PGConnection *)_con handle:(void *)_handle {
+ if (_handle == NULL) {
+ [self release];
+ return nil;
+ }
+ if ((self = [super init])) {
+ self->connection = [_con retain];
+ self->results = _handle;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self clear];
+ [self->connection release];
+ [super dealloc];
+}
+
+/* accessors */
+
+- (BOOL)isValid {
+ return self->results != NULL ? YES : NO;
+}
+
+- (BOOL)containsBinaryTuples {
+#if NG_HAS_BINARY_TUPLES
+ if (self->results == NULL) return NO;
+ return PQbinaryTuples(self->results) ? YES : NO;
+#else
+ return NO;
+#endif
+}
+
+- (NSString *)commandStatus {
+ char *cstr;
+
+ if (self->results == NULL)
+ return nil;
+ if ((cstr = PQcmdStatus(self->results)) == NULL)
+ return nil;
+ return [NSString stringWithCString:cstr];
+}
+
+- (NSString *)commandTuples {
+ char *cstr;
+
+ if (self->results == NULL)
+ return nil;
+ if ((cstr = PQcmdTuples(self->results)) == NULL)
+ return nil;
+ return [NSString stringWithCString:cstr];
+}
+
+/* fields */
+
+- (unsigned)fieldCount {
+ return self->results != NULL ? PQnfields(self->results) : 0;
+}
+
+- (NSString *)fieldNameAtIndex:(unsigned int)_idx {
+ // TODO: charset
+ if (self->results == NULL) return nil;
+ return [NSString stringWithCString:PQfname(self->results, _idx)];
+}
+
+- (int)indexOfFieldNamed:(NSString *)_name {
+ return PQfnumber(self->results, [_name cString]);
+}
+
+- (int)fieldSizeAtIndex:(unsigned int)_idx {
+ if (self->results == NULL) return 0;
+ return PQfsize(self->results, _idx);
+}
+
+- (int)modifierAtIndex:(unsigned int)_idx {
+ if (self->results == NULL) return 0;
+#if NG_HAS_FMOD
+ return PQfmod(self->results, _idx);
+#else
+ return 0;
+#endif
+}
+
+/* tuples */
+
+- (unsigned int)tupleCount {
+ if (self->results == NULL) return 0;
+ return PQntuples(self->results);
+}
+
+- (BOOL)isNullTuple:(int)_tuple atIndex:(unsigned int)_idx {
+ if (self->results == NULL) return NO;
+ return PQgetisnull(self->results, _tuple, _idx) ? YES : NO;
+}
+
+- (void *)rawValueOfTuple:(int)_tuple atIndex:(unsigned int)_idx {
+ if (self->results == NULL) return NULL;
+ return PQgetvalue(self->results, _tuple, _idx);
+}
+
+- (int)lengthOfTuple:(int)_tuple atIndex:(unsigned int)_idx {
+ if (self->results == NULL) return 0;
+ return PQgetlength(self->results, _tuple, _idx);
+}
+
+/* operations */
+
+- (void)clear {
+ if (self->results == NULL) return;
+ PQclear(self->results);
+ self->results = NULL;
+}
+
+@end /* PGResultSet */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>PostgreSQL72</string>
+ <key>CFBundleGetInfoString</key>
+ <string></string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>org.opengroupware.gnustep-db.PostgreSQL72</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string></string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
--- /dev/null
+/*
+ PostgreSQL72Adaptor.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Adaptor.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_Adaptor_H___
+#define ___PostgreSQL72_Adaptor_H___
+
+/*
+ The PostgreSQL72 adaptor.
+
+ The connection dictionary of this adaptor understands these keys:
+ hostName
+ port
+ options
+ tty
+ userName
+ password
+ databaseName
+
+ The adaptor is based on libpq.
+*/
+
+#import <Foundation/NSMapTable.h>
+#import <GDLAccess/EOAdaptor.h>
+#import <GDLAccess/EOAttribute.h>
+
+@class NSString, NSMutableDictionary, NSArray;
+
+@interface PostgreSQL72Adaptor : EOAdaptor
+{
+}
+
+- (id)initWithName:(NSString *)_name;
+
+/* connection management */
+
+- (NSString *)serverName;
+- (NSString *)loginName;
+- (NSString *)loginPassword;
+- (NSString *)databaseName;
+- (NSString *)port;
+- (NSString *)options;
+- (NSString *)tty;
+- (NSString *)newKeyExpression;
+
+/* sequence for primary key generation */
+
+- (NSString *)primaryKeySequenceName;
+
+/* value formatting */
+
+- (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute;
+
+/* attribute typing */
+
+- (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr;
+
+/* classes used */
+
+- (Class)adaptorContextClass; // PostgreSQL72Context
+- (Class)adaptorChannelClass; // PostgreSQL72Channel
+- (Class)expressionClass; // PostgreSQL72Expression
+
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Adaptor.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Adaptor.m 1 2004-08-20 10:38:46Z znek $
+
+#include "common.h"
+#include "PostgreSQL72Adaptor.h"
+#include "PostgreSQL72Context.h"
+#include "PostgreSQL72Channel.h"
+#include "PostgreSQL72Expression.h"
+#include "PostgreSQL72Values.h"
+#include "PGConnection.h"
+
+@implementation PostgreSQL72Adaptor
+
+static BOOL debugOn = NO;
+
+- (id)initWithName:(NSString *)_name {
+ if ((self = [super initWithName:_name])) {
+ }
+ return self;
+}
+
+- (void)gcFinalize {
+}
+
+- (void)dealloc {
+ // NSLog(@"%s", __PRETTY_FUNCTION__);
+ [self gcFinalize];
+ [super dealloc];
+}
+
+/* NSCopying methods */
+
+- (id)copyWithZone:(NSZone *)_zone {
+ return [self retain];
+}
+
+/* connections */
+
+- (NSString *)_copyOfConDictString:(NSString *)_key {
+ return [[[[self connectionDictionary] objectForKey:_key] copy] autorelease];
+}
+
+- (NSString *)serverName {
+ NSString *serverName;
+
+ serverName = [[self connectionDictionary] objectForKey:@"hostName"];
+
+ if (serverName == nil) { // lookup env-variable
+ serverName =
+ [[[NSProcessInfo processInfo] environment] objectForKey:@"PGHOST"];
+ }
+
+ return [[serverName copy] autorelease];
+}
+- (NSString *)loginName {
+ return [self _copyOfConDictString:@"userName"];
+}
+- (NSString *)loginPassword {
+ return [self _copyOfConDictString:@"password"];
+}
+- (NSString *)databaseName {
+ return [self _copyOfConDictString:@"databaseName"];
+}
+
+- (NSString *)port {
+ return [self _copyOfConDictString:@"port"];
+}
+- (NSString *)options {
+ return [self _copyOfConDictString:@"options"];
+}
+- (NSString *)tty {
+ return [self _copyOfConDictString:@"tty"];
+}
+
+/* sequence for primary key generation */
+
+- (NSString *)primaryKeySequenceName {
+ NSString *seqName;
+
+ seqName =
+ [[self pkeyGeneratorDictionary] objectForKey:@"primaryKeySequenceName"];
+ return [[seqName copy] autorelease];
+}
+
+- (NSString *)newKeyExpression {
+ NSString *newKeyExpr;
+
+ newKeyExpr =
+ [[self pkeyGeneratorDictionary] objectForKey:@"newKeyExpression"];
+ return [[newKeyExpr copy] autorelease];
+}
+
+/* formatting */
+
+- (NSString *)charConvertExpressionForAttributeNamed:(NSString *)_attrName {
+ return _attrName;
+}
+
+- (id)formatValue:(id)value forAttribute:(EOAttribute *)attribute {
+ /*
+ This formats values into SQL constants, eg:
+ @"blah" will be converted to 'blah'
+ */
+ NSString *result;
+
+ result = [value stringValueForPostgreSQLType:[attribute externalType]
+ attribute:attribute];
+ if (debugOn) {
+ NSLog(@"formatting value '%@'(%@) result '%@'",
+ value, NSStringFromClass([value class]), result);
+ NSLog(@" value class %@ attr %@ attr type %@",
+ [value class], attribute, [attribute externalType]);
+ }
+ return result;
+}
+
+- (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
+ return YES;
+}
+
+/* types */
+
+- (BOOL)isValidQualifierType:(NSString *)_typeName {
+ return YES;
+}
+
+/* adaptor info */
+
+- (Class)adaptorContextClass {
+ return [PostgreSQL72Context class];
+}
+- (Class)adaptorChannelClass {
+ return [PostgreSQL72Channel class];
+}
+
+- (Class)expressionClass {
+ return [PostgreSQL72Expression class];
+}
+
+@end /* PostgreSQL72Adaptor */
+
+void __linkPostgreSQL72Adaptor(void) {
+ extern void __link_EOAttributePostgreSQL72();
+ extern void __link_NSStringPostgreSQL72();
+ extern void __link_PostgreSQL72ChannelModel();
+ extern void __link_PostgreSQL72Values();
+ ;
+ [PostgreSQL72Channel class];
+ [PostgreSQL72Context class];
+ [PostgreSQL72Exception class];
+ [PostgreSQL72Expression class];
+ __link_EOAttributePostgreSQL72();
+ __link_NSStringPostgreSQL72();
+ //__link_PostgreSQL72ChannelModel();
+ __link_PostgreSQL72Values();
+ __linkPostgreSQL72Adaptor();
+}
--- /dev/null
+/*
+ PostgreSQL72Channel+Model.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Channel+Model.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_ModelFetching_H___
+#define ___PostgreSQL72_ModelFetching_H___
+
+#import "PostgreSQL72Channel.h"
+
+@class NSArray;
+@class EOModel;
+
+@interface PostgreSQL72Channel(ModelFetching)
+
+- (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames;
+- (NSArray *)describeUserNames;
+- (NSArray *)describeTableNames;
+- (NSArray *)describeDatabaseNames;
+
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Channel+Model.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Channel+Model.m 1 2004-08-20 10:38:46Z znek $
+
+#include "PostgreSQL72Channel.h"
+#include "NSString+PostgreSQL72.h"
+#include "EOAttribute+PostgreSQL72.h"
+#import "common.h"
+
+@interface EORelationship(FixMe)
+- (void)addJoin:(id)_join;
+@end
+
+@implementation PostgreSQL72Channel(ModelFetching)
+
+static BOOL debugOn = NO;
+
+- (NSArray *)_attributesForTableName:(NSString *)_tableName {
+ NSMutableArray *attributes;
+ NSString *sqlExpr;
+ NSArray *resultDescription;
+ NSDictionary *row;
+
+ if (![_tableName length])
+ return nil;
+
+ attributes = [self->_attributesForTableName objectForKey:_tableName];
+ if (attributes != nil)
+ return attributes;
+
+ sqlExpr =
+ @"SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull "
+ @"FROM pg_class c, pg_attribute a, pg_type t "
+ @"WHERE c.relname='%@' AND a.attnum>0 AND a.attrelid=c.oid AND "
+ @"a.atttypid=t.oid "
+ @"ORDER BY attnum;";
+ sqlExpr = [NSString stringWithFormat:sqlExpr, _tableName];
+
+ if (![self evaluateExpression:sqlExpr]) {
+ fprintf(stderr,
+ "Could not evaluate column-describe '%s' on table '%s'\n",
+ [sqlExpr cString], [_tableName cString]);
+ return nil;
+ }
+
+ resultDescription = [self describeResults];
+ attributes = [NSMutableArray arrayWithCapacity:16];
+
+ while ((row = [self fetchAttributes:resultDescription withZone:NULL])) {
+ EOAttribute *attribute;
+ NSString *columnName, *externalType, *attrName;
+
+ columnName = [[row objectForKey:@"attname"] stringValue];
+ attrName = [columnName _pgModelMakeInstanceVarName];
+ externalType = [[row objectForKey:@"typname"] stringValue];
+
+ attribute = [[EOAttribute alloc] init];
+ [attribute setColumnName:columnName];
+ [attribute setName:attrName];
+ [attribute setExternalType:externalType];
+ [attribute loadValueClassForExternalPostgreSQLType:externalType];
+ [attributes addObject:attribute];
+ [attribute release]; attribute = nil;
+ }
+ [self->_attributesForTableName setObject:attributes forKey:_tableName];
+ if (debugOn) NSLog(@"%s: got attrs: %@", __PRETTY_FUNCTION__, attributes);
+ return attributes;
+}
+
+- (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName {
+ NSArray *pkNameForTableName = nil;
+ NSMutableArray *primaryKeys = nil;
+ NSString *selectExpression;
+ NSArray *resultDescription = nil;
+ NSString *columnNameKey = nil;
+ NSDictionary *row = nil;
+
+ if ([_tableName length] == 0)
+ return nil;
+
+ pkNameForTableName =
+ [self->_primaryKeysNamesForTableName objectForKey:_tableName];
+
+ if (pkNameForTableName != nil)
+ return pkNameForTableName;
+
+ selectExpression = [NSString stringWithFormat:
+ @"SELECT attname FROM pg_attribute WHERE "
+ @"attrelid IN (SELECT a.indexrelid FROM "
+ @"pg_index a, pg_class b WHERE "
+ @"a.indexrelid = b.oid AND "
+ @"b.relname in (SELECT indexname FROM "
+ @"pg_indexes WHERE "
+ @"tablename = '%@') "
+ @"AND a.indisprimary)", _tableName];
+
+ if (![self evaluateExpression:selectExpression])
+ return nil;
+
+ resultDescription = [self describeResults];
+ columnNameKey = [(EOAttribute *)[resultDescription objectAtIndex:0] name];
+ primaryKeys = [NSMutableArray arrayWithCapacity:4];
+
+ while ((row = [self fetchAttributes:resultDescription withZone:NULL]))
+ [primaryKeys addObject:[row objectForKey:columnNameKey]];
+
+ pkNameForTableName = primaryKeys;
+ [self->_primaryKeysNamesForTableName setObject:pkNameForTableName
+ forKey:_tableName];
+ return pkNameForTableName;
+}
+
+- (NSArray *)_foreignKeysForTableName:(NSString *)_tableName {
+ return nil;
+}
+
+- (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames {
+ NSMutableArray *buildRelShips = [NSMutableArray arrayWithCapacity:64];
+ EOModel *model = AUTORELEASE([EOModel new]);
+ int cnt, tc = [_tableNames count];
+
+ for (cnt = 0; cnt < tc; cnt++) {
+ NSMutableDictionary *relNamesUsed;
+ NSMutableArray *classProperties;
+ NSMutableArray *primaryKeyAttributes;
+ NSString *tableName;
+ NSArray *attributes;
+ NSArray *pkeys;
+ NSArray *fkeys;
+ EOEntity *entity;
+ int cnt2, ac, fkc;
+
+ relNamesUsed = [NSMutableDictionary dictionaryWithCapacity:4];
+ classProperties = [NSMutableArray arrayWithCapacity:16];
+ primaryKeyAttributes = [NSMutableArray arrayWithCapacity:2];
+
+ tableName = [_tableNames objectAtIndex:cnt];
+ attributes = [self _attributesForTableName:tableName];
+ pkeys = [self _primaryKeysNamesForTableName:tableName];
+ fkeys = [self _foreignKeysForTableName:tableName];
+ entity = [[EOEntity new] autorelease];
+ ac = [attributes count];
+ fkc = [fkeys count];
+
+ [entity setName:[tableName _pgModelMakeClassName]];
+ [entity setClassName:
+ [@"EO" stringByAppendingString:
+ [tableName _pgModelMakeClassName]]];
+ [entity setExternalName:tableName];
+ [classProperties addObjectsFromArray:[entity classProperties]];
+ [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]];
+ [model addEntity:entity];
+
+ for (cnt2 = 0; cnt2 < ac; cnt2++) {
+ EOAttribute *attribute = [attributes objectAtIndex:cnt2];
+ NSString *columnName = [attribute columnName];
+
+ attribute = [attributes objectAtIndex:cnt2];
+ columnName = [attribute columnName];
+
+ [entity addAttribute:attribute];
+ [classProperties addObject:attribute];
+
+ if ([pkeys containsObject:columnName])
+ [primaryKeyAttributes addObject:attribute];
+ }
+ [entity setClassProperties:classProperties];
+ [entity setPrimaryKeyAttributes:primaryKeyAttributes];
+
+ for (cnt2 = 0; cnt2 < fkc; cnt2++) {
+ NSDictionary *fkey;
+ NSMutableArray *classProperties;
+ NSString *sa, *da, *dt;
+ EORelationship *rel;
+ EOJoin *join;
+ NSString *relName = nil;
+
+ fkey = [fkeys objectAtIndex:cnt2];
+ classProperties = [NSMutableArray arrayWithCapacity:16];
+ sa = [fkey objectForKey:@"sourceAttr"];
+ da = [fkey objectForKey:@"targetAttr"];
+ dt = [fkey objectForKey:@"targetTable"];
+ rel = [[[EORelationship alloc] init] autorelease];
+ join = [[[EOJoin alloc] init] autorelease];
+
+ if ([pkeys containsObject:sa])
+ relName = [@"to" stringByAppendingString:[dt _pgModelMakeClassName]];
+ else {
+ relName = [@"to" stringByAppendingString:
+ [[sa _pgModelMakeInstanceVarName]
+ _pgStringWithCapitalizedFirstChar]];
+ if ([relName hasSuffix:@"Id"]) {
+ int cLength = [relName cStringLength];
+
+ relName = [relName substringToIndex:cLength - 2];
+ }
+ }
+ if ([relNamesUsed objectForKey:relName] != nil) {
+ int useCount = [[relNamesUsed objectForKey:relName] intValue];
+
+ [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)]
+ forKey:relName];
+ relName = [NSString stringWithFormat:@"%s%d",
+ [relName cString], useCount];
+ }
+ else
+ [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName];
+
+ [rel setName:relName];
+ //[rel setDestinationEntity:(EOEntity *)[dt _pgModelMakeClassName]];
+ [rel setToMany:NO];
+
+ // TODO: EOJoin is removed, fix this ...
+ [(id)join setSourceAttribute:
+ (EOAttribute *)[sa _pgModelMakeInstanceVarName]];
+ [(id)join setDestinationAttribute:
+ (EOAttribute *)[da _pgModelMakeInstanceVarName]];
+ [rel addJoin:join];
+
+ [entity addRelationship:rel];
+ [classProperties addObjectsFromArray:[entity classProperties]];
+ [classProperties addObject:rel];
+ [entity setClassProperties:classProperties];
+ [buildRelShips addObject:rel];
+ }
+
+ [entity setAttributesUsedForLocking:[entity attributes]];
+ }
+
+ [buildRelShips makeObjectsPerformSelector:
+ @selector(replaceStringsWithObjects)];
+ /*
+ // make reverse relations
+ {
+ int cnt, rc = [buildRelShips count];
+
+ for (cnt = 0; cnt < rc; cnt++) {
+ EORelationship *rel = [buildRelShips objectAtIndex:cnt];
+ NSMutableArray *classProperties = [NSMutableArray new];
+ EORelationship *reverse = [rel reversedRelationShip];
+ EOEntity *entity = [rel destinationEntity];
+ NSArray *pkeys = [entity primaryKeyAttributes];
+ BOOL isToMany = [reverse isToMany];
+ EOAttribute *sa = [[[reverse joins] lastObject] sourceAttribute];
+ NSString *relName = nil;
+
+ if ([pkeys containsObject:sa]
+ || isToMany)
+ relName = [@"to" stringByAppendingString:
+ [(EOEntity *)[reverse destinationEntity] name]];
+ else {
+ relName = [@"to" stringByAppendingString:
+ [[[sa name] _pgModelMakeInstanceVarName]
+ _pgStringWithCapitalizedFirstChar]];
+ if ([relName hasSuffix:@"Id"]) {
+ int cLength = [relName cStringLength];
+
+ relName = [relName substringToIndex:cLength - 2];
+ }
+ }
+
+ if ([entity relationshipNamed:relName]) {
+ int cnt = 1;
+ NSString *numName;
+
+ numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt];
+ while ([entity relationshipNamed:numName]) {
+ cnt++;
+ numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt];
+ }
+
+ relName = numName;
+ }
+
+ [reverse setName:relName];
+
+ [entity addRelationship:reverse];
+
+ [classProperties addObjectsFromArray:[entity classProperties]];
+ [classProperties addObject:reverse];
+ [entity setClassProperties:classProperties];
+ }
+ }
+ */
+ [model setAdaptorName:@"PostgreSQL72"];
+ [model setAdaptorClassName:@"PostgreSQL72Adaptor"];
+ [model setConnectionDictionary:
+ [[adaptorContext adaptor] connectionDictionary]];
+
+ return model;
+}
+
+- (NSArray *)_runSingleColumnQuery:(NSString *)_query {
+ NSMutableArray *names;
+ NSArray *resultDescription;
+ NSString *attributeName;
+ NSDictionary *row;
+
+ if (![self evaluateExpression:_query]) {
+ fprintf(stderr, "Could not evaluate expression: '%s'\n", [_query cString]);
+ return nil;
+ }
+
+ resultDescription = [self describeResults];
+ attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name];
+ names = [NSMutableArray arrayWithCapacity:16];
+
+ while ((row = [self fetchAttributes:resultDescription withZone:NULL]))
+ [names addObject:[row objectForKey:attributeName]];
+
+ return names;
+}
+
+- (NSArray *)describeTableNames {
+ NSString *sql;
+
+ sql =
+ @"SELECT relname "
+ @"FROM pg_class "
+ @"WHERE (relkind='r') AND (relname !~ '^pg_') AND "
+ @"(relname !~ '^xinv[0-9]+') "
+ @"ORDER BY relname";
+ return [self _runSingleColumnQuery:sql];
+}
+
+- (NSArray *)describeDatabaseNames {
+ return [self _runSingleColumnQuery:
+ @"SELECT datname FROM pg_database ORDER BY datname"];
+}
+
+- (NSArray *)describeUserNames {
+ return [self _runSingleColumnQuery:@"SELECT usename FROM pg_user"];
+}
+
+@end /* PostgreSQL72Channel(ModelFetching) */
+
+void __link_PostgreSQL72ChannelModel() {
+ // used to force linking of object file
+ __link_PostgreSQL72ChannelModel();
+}
--- /dev/null
+/*
+ PostgreSQL72Channel.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Channel.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_Channel_H___
+#define ___PostgreSQL72_Channel_H___
+
+#import <GDLAccess/EOAdaptorChannel.h>
+#include <libpq-fe.h>
+
+@class NSArray, NSString, NSMutableDictionary;
+@class PGConnection, PGResultSet;
+
+typedef struct {
+ const char *name;
+ Oid type;
+ int size;
+ int modification;
+} PostgreSQL72FieldInfo;
+
+@interface PostgreSQL72Channel : EOAdaptorChannel
+{
+ // connection is valid after an openChannel call
+ PGConnection *connection;
+
+ // valid during -evaluateExpression:
+ PGResultSet *resultSet;
+ int tupleCount;
+ int fieldCount;
+ BOOL containsBinaryData;
+ PostgreSQL72FieldInfo *fieldInfo;
+ NSString *cmdStatus;
+ NSString *cmdTuples;
+ int currentTuple;
+
+ // turns on/off channel debugging
+ BOOL isDebuggingEnabled;
+
+ NSMutableDictionary *_attributesForTableName;
+ NSMutableDictionary *_primaryKeysNamesForTableName;
+
+ int *fieldIndices;
+ NSString **fieldKeys;
+ id *fieldValues;
+}
+
+- (void)setDebugEnabled:(BOOL)_flag;
+- (BOOL)isDebugEnabled;
+
+- (BOOL)isOpen;
+- (BOOL)openChannel;
+- (void)closeChannel;
+
+- (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes
+ withZone:(NSZone *)_zone;
+
+- (BOOL)evaluateExpression:(NSString *)_expression;
+
+// cancelFetch is always called to terminate a fetch
+// (even by primaryFetchAttributes)
+// it frees all fetch-local variables
+- (void)cancelFetch;
+
+// uses dataFormat type information to create EOAttribute objects
+- (NSArray *)describeResults;
+
+@end
+
+@interface NSObject(Sybase10ChannelDelegate)
+
+- (NSArray*)postgreSQLChannel:(PostgreSQL72Channel *)channel
+ willFetchAttributes:(NSArray *)attributes;
+
+- (BOOL)postgreSQLChannel:(PostgreSQL72Channel *)channel
+ willReturnRow:(NSDictionary *)row;
+
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Channel.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Channel.m 1 2004-08-20 10:38:46Z znek $
+
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#import "common.h"
+#import "PostgreSQL72Channel.h"
+#import "PostgreSQL72Adaptor.h"
+#import "PostgreSQL72Exception.h"
+#import "NSString+PostgreSQL72.h"
+#import "PostgreSQL72Values.h"
+#import "EOAttribute+PostgreSQL72.h"
+#include "PGConnection.h"
+
+#ifndef MIN
+# define MIN(x, y) ((x > y) ? y : x)
+#endif
+
+#if PG_MAJOR_VERSION >= 6 && PG_MINOR_VERSION > 3
+# define NG_HAS_NOTICE_PROCESSOR 1
+# define NG_HAS_BINARY_TUPLES 1
+# define NG_HAS_FMOD 1
+#endif
+
+#if PG_MAJOR_VERSION >= 7 && PG_MINOR_VERSION > 3
+# define NG_SET_CLIENT_ENCODING 1
+#endif
+
+#define MAX_CHAR_BUF 16384
+
+@interface PostgreSQL72Channel(Privates)
+- (void)_resetEvaluationState;
+@end
+
+@implementation PostgreSQL72Channel
+
+#if NG_SET_CLIENT_ENCODING
+static NSString *PGClientEncoding = @"Latin1";
+#endif
+static int MaxOpenConnectionCount = -1;
+static BOOL debugOn = NO;
+static NSNull *null = nil;
+static NSNumber *yesObj = nil;
+static Class StringClass = Nil;
+static Class MDictClass = Nil;
+
++ (void)initialize {
+ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
+
+ if (null == nil) null = [[NSNull null] retain];
+ if (yesObj == nil) yesObj = [[NSNumber numberWithBool:YES] retain];
+
+ StringClass = [NSString class];
+ MDictClass = [NSMutableDictionary class];
+
+ MaxOpenConnectionCount = [ud integerForKey:@"PGMaxOpenConnectionCount"];
+ if (MaxOpenConnectionCount < 2)
+ MaxOpenConnectionCount = 50;
+
+ debugOn = [ud boolForKey:@"PGDebugEnabled"];
+}
+
+- (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext {
+ if ((self = [super initWithAdaptorContext:_adaptorContext])) {
+ [self setDebugEnabled:debugOn];
+
+ self->_attributesForTableName = [[MDictClass alloc] initWithCapacity:16];
+ self->_primaryKeysNamesForTableName =
+ [[MDictClass alloc] initWithCapacity:16];
+ }
+ return self;
+}
+
+/* collection */
+
+- (void)dealloc {
+ [self _resetEvaluationState];
+
+ if ([self isOpen])
+ [self closeChannel];
+
+ [self->_attributesForTableName release];
+ [self->_primaryKeysNamesForTableName release];
+ [super dealloc];
+}
+
+/* NSCopying methods */
+
+- (id)copyWithZone:(NSZone *)zone {
+ return [self retain];
+}
+
+/* debugging */
+
+- (void)setDebugEnabled:(BOOL)_flag {
+ self->isDebuggingEnabled = _flag;
+}
+- (BOOL)isDebugEnabled {
+ return self->isDebuggingEnabled;
+}
+
+- (void)receivedMessage:(NSString *)_message {
+ NSLog(@"%@: message: %@", self, _message);
+}
+
+static void _pgMessageProcessor(void *_channel, const char *_msg)
+ __attribute__((unused));
+
+static void _pgMessageProcessor(void *_channel, const char *_msg) {
+ [(id)_channel receivedMessage:
+ _msg ? [StringClass stringWithCString:_msg] : nil];
+}
+
+/* cleanup */
+
+- (void)_resetResults {
+ [self->resultSet clear];
+ [self->resultSet release];
+ self->resultSet = nil;
+}
+
+/* open/close */
+
+static int openConnectionCount = 0;
+
+- (BOOL)isOpen {
+ return [self->connection isValid];
+}
+
+- (BOOL)openChannel {
+ PostgreSQL72Adaptor *adaptor;
+
+ if ([self->connection isValid]) {
+ NSLog(@"%s: Connection already open !!!", __PRETTY_FUNCTION__);
+ return NO;
+ }
+
+ adaptor = (PostgreSQL72Adaptor *)[adaptorContext adaptor];
+
+ if (![super openChannel])
+ return NO;
+
+#if HEAVY_DEBUG
+ NSLog(@"+++++++++ %s: openConnectionCount %d", __PRETTY_FUNCTION__,
+ openConnectionCount);
+#endif
+
+ if (openConnectionCount > MaxOpenConnectionCount) {
+ [PostgreSQL72CouldNotOpenChannelException raise:@"NoMoreConnections"
+ format:
+ @"cannot open a additional connection !"];
+ return NO;
+ }
+
+ self->connection =
+ [[PGConnection alloc] initWithHostName:[adaptor serverName]
+ port:[(id)[adaptor port] stringValue]
+ options:[adaptor options]
+ tty:[adaptor tty] database:[adaptor databaseName]
+ login:[adaptor loginName]
+ password:[adaptor loginPassword]];
+
+ if (![self->connection isValid]) {
+ // could not login ..
+ NSLog(@"WARNING: could not open pgsql channel to %@@%@ host %@:%@",
+ [adaptor loginName],
+ [adaptor databaseName], [adaptor serverName], [adaptor port]);
+ return NO;
+ }
+
+ /* PQstatus */
+ if (![self->connection isConnectionOK]) {
+ NSLog(@"could not open channel to %@@%@",
+ [adaptor databaseName], [adaptor serverName]);
+ [self->connection finish];
+ [self->connection release];
+ self->connection = nil;
+ return NO;
+ }
+
+ /* set message callback */
+ [self->connection setNoticeProcessor:_pgMessageProcessor context:self];
+
+ /* set client encoding */
+#if NG_SET_CLIENT_ENCODING
+ if (![self->connection setClientEncoding:PGClientEncoding]) {
+ NSLog(@"WARNING: could not set client encoding to: '%s'",
+ PGClientEncoding);
+ }
+#endif
+
+ /* log */
+
+ if (isDebuggingEnabled)
+ NSLog(@"PostgreSQL72 connection established: %@", self->connection);
+
+#if HEAVY_DEBUG
+ NSLog(@"---------- %s: %@ opens channel count[%d]", __PRETTY_FUNCTION__,
+ self, openConnectionCount);
+#endif
+
+ openConnectionCount++;
+
+ if (isDebuggingEnabled) {
+ NSLog(@"PostgreSQL72 channel 0x%08X opened (connection=%@)",
+ (unsigned)self, self->connection);
+ }
+ return YES;
+}
+
+- (void)primaryCloseChannel {
+ self->tupleCount = 0;
+ self->fieldCount = 0;
+ self->containsBinaryData = NO;
+
+ if (self->fieldInfo) {
+ free(self->fieldInfo);
+ self->fieldInfo = NULL;
+ }
+
+ [self _resetResults];
+
+ [self->cmdStatus release]; self->cmdStatus = nil;
+ [self->cmdTuples release]; self->cmdTuples = nil;
+
+ if (self->connection) {
+ [self->connection finish];
+#if HEAVY_DEBUG
+ NSLog(@"---------- %s: %@ close channel count[%d]", __PRETTY_FUNCTION__,
+ self, openConnectionCount);
+#endif
+ openConnectionCount--;
+
+ if (isDebuggingEnabled) {
+ fprintf(stderr,
+ "PostgreSQL72 connection dropped 0x%08X (channel=0x%08X)\n",
+ (unsigned)self->connection, (unsigned)self);
+ }
+ [self->connection release];
+ self->connection = nil;
+ }
+}
+
+- (void)closeChannel {
+ [super closeChannel];
+ [self primaryCloseChannel];
+}
+
+/* fetching rows */
+
+- (void)cancelFetch {
+ if (![self isOpen]) {
+ [PostgreSQL72Exception raise:@"ChannelNotOpenException"
+ format:@"No fetch in progress, connection is not open"
+ @" (channel=%@)", self];
+ }
+
+#if HEAVY_DEBUG
+ NSLog(@"canceling fetch (%i tuples remaining).",
+ (self->tupleCount - self->currentTuple));
+#endif
+
+ self->tupleCount = 0;
+ self->currentTuple = 0;
+ self->fieldCount = 0;
+ self->containsBinaryData = NO;
+
+ if (self->fieldInfo) {
+ free(self->fieldInfo);
+ self->fieldInfo = NULL;
+ }
+ [self _resetResults];
+
+ [self->cmdStatus release]; self->cmdStatus = nil;
+ [self->cmdTuples release]; self->cmdTuples = nil;
+
+ /* new caches which require a constant _attributes argument */
+ if (self->fieldIndices) free(self->fieldIndices); self->fieldIndices = NULL;
+ if (self->fieldKeys) free(self->fieldKeys); self->fieldKeys = NULL;
+ if (self->fieldValues) free(self->fieldValues); self->fieldValues = NULL;
+
+ [super cancelFetch];
+}
+
+- (NSArray *)describeResults {
+ int cnt;
+ NSMutableArray *result = nil;
+ NSMutableDictionary *usedNames = nil;
+
+ if (![self isFetchInProgress]) {
+ [PostgreSQL72Exception raise:@"NoFetchInProgress"
+ format:@"No fetch in progress (channel=%@)", self];
+ }
+
+ result = [[NSMutableArray alloc] initWithCapacity:self->fieldCount];
+ usedNames = [[MDictClass alloc] initWithCapacity:self->fieldCount];
+
+ for (cnt = 0; cnt < self->fieldCount; cnt++) {
+ EOAttribute *attribute = nil;
+ NSString *columnName;
+ NSString *attrName;
+
+ columnName =
+ [[StringClass alloc] initWithCString:self->fieldInfo[cnt].name];
+ attrName = [columnName _pgModelMakeInstanceVarName];
+
+ if ([[usedNames objectForKey:attrName] boolValue]) {
+ // TODO: move name generation code to different method!
+ int cnt2 = 0;
+ char buf[64];
+ NSString *newAttrName = nil;
+
+ for (cnt2 = 2; cnt2 < 100; cnt2++) {
+ NSString *s;
+
+ sprintf(buf, "%i", cnt2);
+
+ s = [[StringClass alloc] initWithCString:buf];
+ newAttrName = [attrName stringByAppendingString:s];
+ [s release]; s= nil;
+
+ if (![[usedNames objectForKey:newAttrName] boolValue]) {
+ attrName = newAttrName;
+ break;
+ }
+ }
+ }
+ [usedNames setObject:yesObj forKey:attrName];
+
+ attribute = [[EOAttribute alloc] init];
+ [attribute setName:attrName];
+ [attribute setColumnName:columnName];
+
+ //NSLog(@"column: %@", columnName);
+
+ [attribute loadValueClassAndTypeUsingPostgreSQLType:
+ self->fieldInfo[cnt].type
+ size:self->fieldInfo[cnt].size
+ modification:self->fieldInfo[cnt].modification
+ binary:self->containsBinaryData];
+
+ [result addObject:attribute];
+
+ [columnName release]; columnName = nil;
+ [attribute release]; attribute = nil;
+ }
+
+ [usedNames release];
+ usedNames = nil;
+
+ return [result autorelease];
+}
+
+- (void)_fillFieldNamesForAttributes:(NSArray *)_attributes
+ count:(unsigned)attrCount
+{
+ // Note: this optimization requires that the "_attributes" array does
+ // note change between invocations!
+ // TODO: should add a sanity check for that!
+ NSMutableArray *fieldNames;
+ unsigned nFields, i;
+ unsigned cnt;
+
+ if (self->fieldIndices)
+ return;
+
+ self->fieldIndices = calloc(attrCount + 2, sizeof(int));
+
+ // TODO: we could probably cache the field-name array for much more speed !
+ fieldNames = [[NSMutableArray alloc] initWithCapacity:32];
+ nFields = [self->resultSet fieldCount];
+ for (i = 0; i < nFields; i++)
+ [fieldNames addObject:[self->resultSet fieldNameAtIndex:i]];
+
+ for (cnt = 0; cnt < attrCount; cnt++) {
+ EOAttribute *attribute;
+
+ attribute = [_attributes objectAtIndex:cnt];
+#if GDL_USE_PQFNUMBER_INDEX
+ self->fieldIndices[cnt] =
+ [self->resultSet indexOfFieldNamed:[attribute columnName]];
+#else
+ self->fieldIndices[cnt] =
+ [fieldNames indexOfObject:[attribute columnName]];
+#endif
+
+ if (self->fieldIndices[cnt] == NSNotFound) {
+ [PostgreSQL72Exception raiseWithFormat:
+ @"attribute %@ not covered by query",
+ attribute];
+ }
+ [fieldNames replaceObjectAtIndex:self->fieldIndices[cnt] withObject:null];
+ }
+ [fieldNames release]; fieldNames = nil;
+}
+
+- (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes
+ withZone:(NSZone *)_zone
+{
+ NSMutableDictionary *row;
+ unsigned attrCount;
+ int *indices;
+ unsigned cnt, fieldDictCount;
+
+ if (self->currentTuple == self->tupleCount) {
+ if (self->resultSet != nil) [self cancelFetch];
+ return nil;
+ }
+
+ attrCount = [_attributes count];
+ [self _fillFieldNamesForAttributes:_attributes count:attrCount];
+ indices = self->fieldIndices;
+
+ if (self->fieldKeys == NULL)
+ self->fieldKeys = calloc(attrCount + 1, sizeof(NSString *));
+ if (self->fieldValues == NULL)
+ self->fieldValues = calloc(attrCount + 1, sizeof(id));
+ fieldDictCount = 0;
+
+ for (cnt = 0; cnt < attrCount; cnt++) {
+ EOAttribute *attribute;
+ NSString *attrName;
+ id value = nil;
+ Class valueClass = Nil;
+ const char *pvalue;
+ int vallen;
+
+ attribute = [_attributes objectAtIndex:cnt];
+ attrName = [attribute name];
+
+ if ([self->resultSet isNullTuple:self->currentTuple atIndex:indices[cnt]]){
+ self->fieldKeys[fieldDictCount] = attrName;
+ self->fieldValues[fieldDictCount] = null;
+ fieldDictCount++;
+ continue;
+ }
+
+ valueClass = NSClassFromString([attribute valueClassName]);
+ if (valueClass == Nil) {
+ NSLog(@"ERROR(%s): %@: got no value class for column:\n"
+ @" attribute=%@\n type=%@",
+ __PRETTY_FUNCTION__, self,
+ attrName, [attribute externalType]);
+ continue;
+ }
+
+ pvalue = [self->resultSet rawValueOfTuple:self->currentTuple
+ atIndex:indices[cnt]];
+ vallen = [self->resultSet lengthOfTuple:self->currentTuple
+ atIndex:indices[cnt]];
+
+ if (self->containsBinaryData) {
+ // pvalue is stored in internal representation
+
+ value = [valueClass valueFromBytes:pvalue length:vallen
+ postgreSQLType:[attribute externalType]
+ attribute:attribute
+ adaptorChannel:self];
+ }
+ else {
+ // pvalue is ascii string
+
+ value = [valueClass valueFromCString:pvalue length:vallen
+ postgreSQLType:[attribute externalType]
+ attribute:attribute
+ adaptorChannel:self];
+ }
+ if (value == nil) {
+ NSLog(@"ERROR(%s): %@: got no value for column:\n"
+ @" attribute=%@\n valueClass=%@\n type=%@",
+ __PRETTY_FUNCTION__, self,
+ attrName, NSStringFromClass(valueClass),
+ [attribute externalType]);
+ continue;
+ }
+
+ /* add to dictionary */
+ self->fieldKeys[fieldDictCount] = attrName;
+ self->fieldValues[fieldDictCount] = value;
+ fieldDictCount++;
+ }
+
+ self->currentTuple++;
+
+ // TODO: we would need to have a copy on write dict here, ideally with
+ // the keys being reused for each fetch-loop
+ row = [[MDictClass alloc] initWithObjects:self->fieldValues
+ forKeys:self->fieldKeys
+ count:fieldDictCount];
+ return [row autorelease];
+}
+
+/* sending sql to server */
+
+- (void)_resetEvaluationState {
+ self->isFetchInProgress = NO;
+ self->tupleCount = 0;
+ self->fieldCount = 0;
+ self->currentTuple = 0;
+ self->containsBinaryData = NO;
+ if (self->fieldInfo) {
+ free(self->fieldInfo);
+ self->fieldInfo = NULL;
+ }
+
+ /* new caches which require a constant _attributes argument */
+ if (self->fieldIndices) free(self->fieldIndices); self->fieldIndices = NULL;
+ if (self->fieldKeys) free(self->fieldKeys); self->fieldKeys = NULL;
+ if (self->fieldValues) free(self->fieldValues); self->fieldValues = NULL;
+}
+
+- (NSException *)_processEvaluationTuplesOKForExpression:(NSString *)_sql {
+ int i;
+
+ self->isFetchInProgress = YES;
+
+ self->tupleCount = [self->resultSet tupleCount];
+ self->fieldCount = [self->resultSet fieldCount];
+ self->containsBinaryData = [self->resultSet containsBinaryTuples];
+
+ self->fieldInfo =
+ calloc(self->fieldCount + 1, sizeof(PostgreSQL72FieldInfo));
+ for (i = 0; i < self->fieldCount; i++) {
+ self->fieldInfo[i].name = PQfname(self->resultSet->results, i);
+ self->fieldInfo[i].type = PQftype(self->resultSet->results, i);
+ self->fieldInfo[i].size = [self->resultSet fieldSizeAtIndex:i];
+ self->fieldInfo[i].modification = [self->resultSet modifierAtIndex:i];
+ }
+
+ self->cmdStatus = [[self->resultSet commandStatus] copy];
+ self->cmdTuples = [[self->resultSet commandTuples] copy];
+
+ if (delegateRespondsTo.didEvaluateExpression)
+ [delegate adaptorChannel:self didEvaluateExpression:_sql];
+
+#if HEAVY_DEBUG
+ NSLog(@"tuples %i fields %i status %@",
+ self->tupleCount, self->fieldCount, self->cmdStatus);
+#endif
+ return nil;
+}
+
+- (NSException *)_handleBadResponseError {
+ NSString *s;
+
+ [self _resetResults];
+
+ s = [NSString stringWithFormat:@"bad pgsql response (channel=%@): %@",
+ self, [self->connection errorMessage]];
+ return [PostgreSQL72Exception exceptionWithName:@"PostgreSQL72BadResponse"
+ reason:s userInfo:nil];
+}
+- (NSException *)_handleNonFatalEvaluationError {
+ NSString *s;
+
+ [self _resetResults];
+
+ s = [NSString stringWithFormat:@"pgsql error (channel=%@): %@",
+ self, [self->connection errorMessage]];
+ return [PostgreSQL72Exception exceptionWithName:@"PostgreSQL72Error"
+ reason:s userInfo:nil];
+}
+- (NSException *)_handleFatalEvaluationError {
+ NSString *s;
+
+ [self _resetResults];
+
+ s = [NSString stringWithFormat:@"fatal pgsql error (channel=%@): %@",
+ self, [self->connection errorMessage]];
+ return [PostgreSQL72Exception exceptionWithName:@"PostgreSQL72FatalError"
+ reason:s userInfo:nil];
+}
+
+- (NSException *)evaluateExpressionX:(NSString *)_expression {
+ BOOL result;
+
+ *(&result) = YES;
+
+ if (_expression == nil) {
+ return [NSException exceptionWithName:NSInvalidArgumentException
+ reason:@"parameter for evaluateExpression: "
+ @"must not be null"
+ userInfo:nil];
+ }
+
+ *(&_expression) = [[_expression mutableCopy] autorelease];
+
+ if (delegateRespondsTo.willEvaluateExpression) {
+ EODelegateResponse response;
+
+ response = [delegate adaptorChannel:self
+ willEvaluateExpression:
+ (NSMutableString *)_expression];
+
+ if (response == EODelegateRejects) {
+ return [NSException exceptionWithName:@"EODelegateRejects"
+ reason:@"delegate rejected insert"
+ userInfo:nil];
+ }
+ if (response == EODelegateOverrides)
+ return nil;
+ }
+
+ if (![self isOpen]) {
+ return [PostgreSQL72Exception exceptionWithName:@"ChannelNotOpenException"
+ reason:
+ @"PostgreSQL72 connection is not open"
+ userInfo:nil];
+ }
+ if (self->resultSet != nil) {
+ return [PostgreSQL72Exception exceptionWithName:
+ @"CommandInProgressException"
+ reason:@"an evaluation is in progress"
+ userInfo:nil];
+ }
+
+ if (isDebuggingEnabled)
+ NSLog(@"PG0x%08X SQL: %@", (unsigned)self, _expression);
+
+ [self _resetEvaluationState];
+
+ self->resultSet = [[self->connection execute:_expression] retain];
+ if (self->resultSet == nil) {
+ return [PostgreSQL72Exception exceptionWithName:@"ExecutionFailed"
+ reason:@"the PQexec() failed"
+ userInfo:nil];
+ }
+
+ /* process results */
+
+ switch (PQresultStatus(self->resultSet->results)) {
+ case PGRES_EMPTY_QUERY:
+ case PGRES_COMMAND_OK:
+ [self _resetResults];
+
+ if (delegateRespondsTo.didEvaluateExpression)
+ [delegate adaptorChannel:self didEvaluateExpression:_expression];
+ return nil;
+
+ case PGRES_TUPLES_OK:
+ return [self _processEvaluationTuplesOKForExpression:_expression];
+
+ case PGRES_COPY_OUT:
+ case PGRES_COPY_IN:
+ [self _resetResults];
+ return [PostgreSQL72Exception exceptionWithName:@"UnsupportedOperation"
+ reason:@"copy(out|in) not supported"
+ userInfo:nil];
+
+ case PGRES_BAD_RESPONSE:
+ return [self _handleBadResponseError];
+ case PGRES_NONFATAL_ERROR:
+ return [self _handleNonFatalEvaluationError];
+ case PGRES_FATAL_ERROR:
+ return [self _handleFatalEvaluationError];
+
+ default:
+ return [NSException exceptionWithName:@"PostgreSQLEvalFailed"
+ reason:@"generic reason"
+ userInfo:nil];
+ }
+}
+- (BOOL)evaluateExpression:(NSString *)_sql {
+ NSException *e;
+ NSString *n;
+
+ if ((e = [self evaluateExpressionX:_sql]) == nil)
+ return YES;
+
+ /* for compatibility with non-X methods, translate some errors to a bool */
+ n = [e name];
+ if ([n isEqualToString:@"EOEvaluationError"])
+ return NO;
+ if ([n isEqualToString:@"EODelegateRejects"])
+ return NO;
+
+ [e raise];
+ return NO;
+}
+
+/* description */
+
+- (NSString *)description {
+ NSMutableString *ms;
+
+ ms = [NSMutableString stringWithCapacity:128];
+ [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+ if (self->connection)
+ [ms appendFormat:@" connection=%@", self->connection];
+ else
+ [ms appendString:@" not-connected"];
+ [ms appendString:@">"];
+ return ms;
+}
+
+@end /* PostgreSQL72Channel */
+
+@implementation PostgreSQL72Channel(PrimaryKeyGeneration)
+
+- (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity {
+ NSArray *pkeys;
+ PostgreSQL72Adaptor *adaptor;
+ NSString *seqName, *seq;
+ NSDictionary *pkey;
+
+ pkeys = [_entity primaryKeyAttributeNames];
+ adaptor = (id)[[self adaptorContext] adaptor];
+ seqName = [adaptor primaryKeySequenceName];
+ pkey = nil;
+ seq = nil;
+
+ seq = [seqName length] > 0
+ ? [StringClass stringWithFormat:@"SELECT NEXTVAL ('%@')", seqName]
+ : [adaptor newKeyExpression];
+
+ // TODO: since we use evaluateExpressionX, we should not see exceptions?
+ NS_DURING {
+ if ([self evaluateExpressionX:seq] == nil) {
+ id key = nil;
+
+ if (self->tupleCount > 0) {
+ if ([self->resultSet isNullTuple:0 atIndex:0])
+ key = [null retain];
+ else {
+ const char *pvalue;
+ int vallen;
+
+ if (self->containsBinaryData) {
+#if COCOA_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
+ NSLog(@"%s: binary data not implemented!", __PRETTY_FUNCTION__);
+#else
+ [self notImplemented:_cmd];
+#endif
+ }
+
+ pvalue = [self->resultSet rawValueOfTuple:0 atIndex:0];
+ vallen = [self->resultSet lengthOfTuple:0 atIndex:0];
+
+ if (pvalue)
+ key = [[NSNumber alloc] initWithInt:atoi(pvalue)];
+ }
+ }
+ [self cancelFetch];
+
+ if (key) {
+ pkey = [NSDictionary dictionaryWithObject:key
+ forKey:[pkeys objectAtIndex:0]];
+ [key release]; key = nil;
+ }
+ }
+ }
+ NS_HANDLER
+ pkey = nil;
+ NS_ENDHANDLER;
+
+ return pkey;
+}
+
+@end /* PostgreSQL72Channel(PrimaryKeyGeneration) */
+
+void __link_PostgreSQL72Channel() {
+ // used to force linking of object file
+ __link_PostgreSQL72Channel();
+}
--- /dev/null
+/*
+ PostgreSQL72Context.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Context.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_Context_H___
+#define ___PostgreSQL72_Context_H___
+
+#import <GDLAccess/EOAdaptorContext.h>
+
+@interface PostgreSQL72Context : EOAdaptorContext
+
+- (BOOL)primaryBeginTransaction;
+- (BOOL)primaryCommitTransaction;
+- (BOOL)primaryRollbackTransaction;
+
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Context.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Context.m 1 2004-08-20 10:38:46Z znek $
+
+#import "PostgreSQL72Context.h"
+#import "PostgreSQL72Channel.h"
+#include "common.h"
+
+@implementation PostgreSQL72Context
+
+- (void)channelDidInit:_channel {
+ if ([channels count] > 0) {
+ [NSException raise:@"TooManyOpenChannelsException"
+ format:@"SybaseAdaptor10 only supports one channel per context"];
+ }
+ [super channelDidInit:_channel];
+}
+
+- (BOOL)primaryBeginTransaction {
+ BOOL result;
+
+ result = [[[channels lastObject]
+ nonretainedObjectValue]
+ evaluateExpression:@"BEGIN TRANSACTION"];
+
+ return result;
+}
+
+- (BOOL)primaryCommitTransaction {
+ BOOL result;
+
+ result = [[[channels lastObject]
+ nonretainedObjectValue]
+ evaluateExpression:@"COMMIT TRANSACTION"];
+
+ return result;
+}
+
+- (BOOL)primaryRollbackTransaction {
+ BOOL result;
+
+ result = [[[channels lastObject]
+ nonretainedObjectValue]
+ evaluateExpression:@"ROLLBACK TRANSACTION"];
+ return result;
+}
+
+- (BOOL)canNestTransactions {
+ return NO;
+}
+
+// NSCopying methods
+
+- (id)copyWithZone:(NSZone *)zone {
+ return [self retain];
+}
+
+@end /* PostgreSQL72Context */
+
+void __link_PostgreSQL72Context() {
+ // used to force linking of object file
+ __link_PostgreSQL72Context();
+}
--- /dev/null
+/*
+ PostgreSQL72Exception.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Exception.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_Exception_H___
+#define ___PostgreSQL72_Exception_H___
+
+#import <Foundation/NSException.h>
+
+@interface PostgreSQL72Exception : NSException
+{
+}
+
++ (void)raiseWithFormat:(NSString *)_format, ...;
+
+@end
+
+@interface PostgreSQL72CouldNotOpenChannelException : PostgreSQL72Exception
+{
+}
+@end
+
+@interface PostgreSQL72CouldNotConnectException : PostgreSQL72CouldNotOpenChannelException
+{
+}
+@end
+
+@interface PostgreSQL72CouldNotBindException : PostgreSQL72Exception
+{
+}
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Exception.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Exception.m 1 2004-08-20 10:38:46Z znek $
+
+#include <GDLAccess/GDLAccess.h>
+#include "PostgreSQL72Exception.h"
+#include "common.h"
+#include <stdarg.h>
+
+@implementation PostgreSQL72Exception
+
++ (void)raiseWithFormat:(NSString *)_format, ... {
+ NSString *tmp = nil;
+ va_list ap;
+
+ va_start(ap, _format);
+ tmp = [[NSString alloc] initWithFormat:_format arguments:ap];
+ va_end(ap);
+
+ [tmp autorelease];
+
+ [[[self alloc] initWithName:NSStringFromClass([self class])
+ reason:tmp userInfo:nil]
+ raise];
+}
+
+@end /* PostgreSQL72Exception */
+
+@implementation PostgreSQL72CouldNotOpenChannelException
+@end
+
+@implementation PostgreSQL72CouldNotConnectException
+@end
+
+@implementation PostgreSQL72CouldNotBindException
+@end
+
+void __link_PostgreSQL72Exception() {
+ // used to force linking of object file
+ __link_PostgreSQL72Exception();
+}
--- /dev/null
+/*
+ PostgreSQL72Expression.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Expression.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___Postgre_SQLExpression_H___
+#define ___Postgre_SQLExpression_H___
+
+#include <GDLAccess/EOSQLExpression.h>
+
+@class NSString, NSArray;
+@class EOSQLQualifier, EOAdaptorChannel;
+
+@interface PostgreSQL72Expression : EOSQLExpression
+
++ (Class)selectExpressionClass;
+
+@end
+
+@interface PostgreSQL72SelectSQLExpression : EOSelectSQLExpression
+{
+ BOOL lock;
+}
+
+- (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel;
+
+- (NSString *)fromClause;
+
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Expression.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Expression.m 1 2004-08-20 10:38:46Z znek $
+
+#include <Foundation/Foundation.h>
+#include <GDLAccess/EOAccess.h>
+#include "PostgreSQL72Expression.h"
+
+@implementation PostgreSQL72Expression
+
++ (Class)selectExpressionClass {
+ return [PostgreSQL72SelectSQLExpression class];
+}
+
+@end
+
+@implementation PostgreSQL72SelectSQLExpression
+
+- (id)selectExpressionForAttributes:(NSArray *)attributes
+ lock:(BOOL)flag
+ qualifier:(EOSQLQualifier *)qualifier
+ fetchOrder:(NSArray *)fetchOrder
+ channel:(EOAdaptorChannel *)channel {
+
+ lock = flag;
+ [super selectExpressionForAttributes:attributes
+ lock:flag
+ qualifier:qualifier
+ fetchOrder:fetchOrder
+ channel:channel];
+ return self;
+}
+
+- (NSString *)fromClause {
+ NSMutableString *fromClause;
+ NSEnumerator *enumerator;
+ BOOL first = YES;
+ id key;
+
+ fromClause = [NSMutableString stringWithCString:" "];
+ enumerator = [fromListEntities objectEnumerator];
+
+ // Compute the FROM list from all the aliases found in
+ // entitiesAndPropertiesAliases dictionary. Note that this dictionary
+ // contains entities and relationships. The last ones are there for
+ // flattened attributes over reflexive relationships.
+
+ while((key = [enumerator nextObject])) {
+ if(first) first = NO;
+ else [fromClause appendString:@", "];
+
+ [fromClause appendFormat:@"%@ %@",
+ [key isKindOfClass:[EORelationship class]]
+ ? [[key destinationEntity] externalName] // flattened attribute
+ : [key externalName], // EOEntity
+ [entitiesAndPropertiesAliases objectForKey:key]];
+
+#if 0
+ if (lock) [fromClause appendString:@" HOLDLOCK"];
+#endif
+ }
+
+ return fromClause;
+}
+
+@end
+
+void __link_PostgreSQL72Expression() {
+ // used to force linking of object file
+ __link_PostgreSQL72Expression();
+}
--- /dev/null
+/*
+ PostgreSQL72Values.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Values.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL72_Values_H___
+#define ___PostgreSQL72_Values_H___
+
+#import <Foundation/NSObject.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSDate.h>
+#import <GDLAccess/EONull.h>
+#import "PostgreSQL72Exception.h"
+
+@class EOAttribute;
+@class PostgreSQL72Channel;
+
+@interface PostgreSQL72DataTypeMappingException : PostgreSQL72Exception
+
+- (id)initWithObject:(id)_obj
+ forAttribute:(EOAttribute *)_attr
+ andPostgreSQLType:(NSString *)_dt
+ inChannel:(PostgreSQL72Channel *)_channel;
+
+@end
+
+@protocol PostgreSQL72Values
+
++ (id)valueFromCString:(const char *)_cstr length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel;
+
++ (id)valueFromBytes:(const void *)_bytes length:(int)_length
+ postgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+ adaptorChannel:(PostgreSQL72Channel *)_channel;
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute;
+
+@end
+
+@interface NSString(PostgreSQL72Values) < PostgreSQL72Values >
+@end
+
+@interface NSNumber(PostgreSQL72Values) < PostgreSQL72Values >
+@end
+
+@interface NSData(PostgreSQL72Values) < PostgreSQL72Values >
+@end
+
+@interface NSCalendarDate(PostgreSQL72Values) < PostgreSQL72Values >
+@end
+
+@interface EONull(PostgreSQL72Values)
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute;
+
+@end
+
+#endif
--- /dev/null
+/*
+ PostgreSQL72Values.m
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+
+ Author: Helge Hess (helge@mdlink.de)
+
+ This file is part of the PostgreSQL72 Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: PostgreSQL72Values.m 1 2004-08-20 10:38:46Z znek $
+
+#import "PostgreSQL72Values.h"
+#import "common.h"
+
+#if !LIB_FOUNDATION_LIBRARY
+@interface PostgreSQL72DataTypeMappingException(Privates)
+- (void)setName:(NSString *)_name;
+- (void)setReason:(NSString *)_reason;
+- (void)setUserInfo:(NSDictionary *)_ui;
+@end
+#endif
+
+@implementation PostgreSQL72DataTypeMappingException
+
+- (id)initWithObject:(id)_obj
+ forAttribute:(EOAttribute *)_attr
+ andPostgreSQLType:(NSString *)_dt
+ inChannel:(PostgreSQL72Channel *)_channel;
+{
+ NSString *typeName = nil;
+
+ typeName = _dt;
+
+ if (typeName == nil)
+ typeName = [NSString stringWithFormat:@"Oid[%i]", _dt];
+
+ // TODO: fix for Cocoa/gstep Foundation?
+ [self setName:@"DataTypeMappingNotSupported"];
+ [self setReason:[NSString stringWithFormat:
+ @"mapping between %@<Class:%@> and "
+ @"postgres type %@ is not supported",
+ [_obj description],
+ NSStringFromClass([_obj class]),
+ typeName]];
+
+ [self setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ _attr, @"attribute",
+ _channel, @"channel",
+ _obj, @"object",
+ nil]];
+ return self;
+}
+
+@end /* PostgreSQL72DataTypeMappingException */
+
+@implementation NSNull(PostgreSQL72Values)
+
+- (NSString *)stringValueForPostgreSQLType:(NSString *)_type
+ attribute:(EOAttribute *)_attribute
+{
+ return @"null";
+}
+
+@end /* NSNull(PostgreSQL72Values) */
+
+
+void __link_PostgreSQL72Values() {
+ // used to force linking of object file
+ __link_PostgreSQL72Values();
+}
--- /dev/null
+# $Id: README 1 2004-08-20 10:38:46Z znek $
+
+Install PostgreSQL:
+
+ cd /INTERNET/suse72/dvd/
+ cd ap3
+ rpm -Uvh postgresql.rpm
+ cd ap2
+ rpm -Uvh postgresql-lib.rpm
+ rpm -Uvh postgresql-server.rpm
+ rpm -Uvh postgresql-devel.rpm
+
+Configure PostgreSQL:
+
+ su - postgres
+ vi .bashrc
+ -> export PGDATA=/var/lib/pgsql/data
+ source .bashrc
+ initdb
+
+ su - root
+ /etc/rc.d/postgresql start
+
+ su - postgres
+ createdb OpenGroupware
+ createuser ogo
+
+ vi data/pg_hba.conf
+ > add line: "host all 192.168.0.1 255.255.255.0 trust"
+
+PostgreSQL starten:
+ /etc/rc.d/postgresql restart
+
+Configure the Adaptor
+ PGDebugEnabled
+
+
+NOTES
+=====
+
+Querying the tables of a database
+---------------------------------
+
+SELECT relname
+ FROM pg_class
+ WHERE ( relkind = 'r') AND relname !~ '^pg_'
+ AND relname !~ '^xinv[0-9]+'
+ ORDER BY relname;
+
+und die infos dazu mit:
+
+SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull
+ FROM pg_class c, pg_attribute a, pg_type t
+ WHERE c.relname = 'TABELLENNAME_HERE' AND
+ a.attnum > 0 AND a.attrelid = c.oid
+ AND a.atttypid = t.oid
+ ORDER BY attnum;
+
+Quering the databases of a server
+---------------------------------
+
+ SELECT * FROM pg_database
+
+You need a database to connect PostgreSQL using libpq, but 'template1' should
+always be available.
+
+Fetch DB-names and their DBA:
+ SELECT DISTINCT dbs.datname, users.usename
+ FROM pg_database dbs, pg_user users
+ WHERE dbs.datdba=users.usesysid
--- /dev/null
+# $Id: TODO 1 2004-08-20 10:38:46Z znek $
+
+- cache field-names in PostgreSQL72Channel -primaryFetch (see TODO)
--- /dev/null
+# $Id: Version 1 2004-08-20 10:38:46Z znek $
+
+SUBMINOR_VERSION:=33
--- /dev/null
+/*
+ common.h
+
+ Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
+ Copyright (C) 2000-2004 SKYRIX Software AG and Helge Hess
+
+ Author: Helge Hess (helge.hess@opengroupware.org)
+
+ This file is part of the PostgreSQL Adaptor Library
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+// $Id: common.h 1 2004-08-20 10:38:46Z znek $
+
+#ifndef ___PostgreSQL_common_H___
+#define ___PostgreSQL_common_H___
+
+#import <objc/objc-api.h>
+
+#if LIB_FOUNDATION_BOEHM_GC
+# include <objc/gc.h>
+# include <objc/gc_typed.h>
+# include <extensions/GarbageCollector.h>
+#endif
+
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#import <Foundation/Foundation.h>
+
+#if LIB_FOUNDATION_LIBRARY
+# import <Foundation/exceptions/GeneralExceptions.h>
+#else
+# include <NGExtensions/NGObjectMacros.h>
+#endif
+
+#import <GDLAccess/EOAccess.h>
+
+#endif /* ___PostgreSQL_common_H___ */
--- /dev/null
+{
+ hostName = "localhost";
+ userName = "helge";
+ password = "helgehelge";
+ databaseName = "hhtest1";
+ port = 5432;
+}
--- /dev/null
+// $Id: gdltest.m 1 2004-08-20 10:38:46Z znek $
+
+#import <Foundation/Foundation.h>
+#import <EOAccess/EOAccess.h>
+#include <NGExtensions/NGExtensions.h>
+
+int main(int argc, char **argv, char **env) {
+ EOModel *m = nil;
+ EOAdaptor *a;
+ EOAdaptorContext *ctx;
+ EOAdaptorChannel *ch;
+ NSDictionary *conDict;
+ NSString *expr;
+
+ [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+
+ NS_DURING {
+
+ conDict = [NSDictionary dictionaryWithContentsOfFile:@"condict.plist"];
+ NSLog(@"condict is %@", conDict);
+
+ if ((a = [EOAdaptor adaptorWithName:@"PostgreSQL"]) == nil) {
+ NSLog(@"found no PostgreSQL adaptor ..");
+ exit(1);
+ }
+
+ NSLog(@"got adaptor %@", a);
+ [a setConnectionDictionary:conDict];
+ NSLog(@"got adaptor with condict %@", a);
+
+ ctx = [a createAdaptorContext];
+ ch = [ctx createAdaptorChannel];
+
+#if 1
+ m = AUTORELEASE([[EOModel alloc] initWithContentsOfFile:@"test.eomodel"]);
+ if (m) {
+ [a setModel:m];
+ [a setConnectionDictionary:conDict];
+ }
+#endif
+
+ expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"];
+
+ NSLog(@"opening channel ..");
+
+ [ch setDebugEnabled:YES];
+
+ if ([ch openChannel]) {
+ NSLog(@"channel is open");
+
+ if ([ctx beginTransaction]) {
+ NSLog(@"began tx ..");
+
+ /* do something */
+ {
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ EOEntity *e;
+ EOSQLQualifier *q;
+ NSArray *attrs;
+
+#if 1
+ /* fetch some expr */
+
+ if (expr) {
+ if ([ch evaluateExpression:expr]) {
+ NSDictionary *record;
+
+ attrs = [ch describeResults];
+ NSLog(@"results: %@", attrs);
+
+ while ((record = [ch fetchAttributes:attrs withZone:nil]))
+ NSLog(@"fetched %@", record);
+ }
+ }
+#endif
+ /* fetch some doof records */
+
+ e = [m entityNamed:@"Doof"];
+ NSLog(@"entity: %@", e);
+ if (e == nil)
+ exit(1);
+
+ q = [e qualifier];
+ attrs = [e attributes];
+
+ if ([ch selectAttributes:attrs
+ describedByQualifier:q
+ fetchOrder:nil
+ lock:NO]) {
+ NSDictionary *record;
+
+ while ((record = [ch fetchAttributes:attrs withZone:nil])) {
+ NSLog(@"fetched %@ birthday %@",
+ [record valueForKey:@"pkey"],
+ [record valueForKey:@"companyId"]);
+ }
+ }
+ else
+ NSLog(@"Could not select ..");
+
+ /* fetch some team records */
+
+ if ((e = [m entityNamed:@"Team"])) {
+ q = [e qualifier];
+ attrs = [e attributes];
+
+ if ([ch selectAttributes:attrs
+ describedByQualifier:q
+ fetchOrder:nil
+ lock:NO]) {
+ NSDictionary *record;
+
+ while ((record = [ch fetchAttributes:attrs withZone:nil])) {
+ NSLog(@"fetched %@ birthday %@",
+ [record valueForKey:@"description"],
+ [record valueForKey:@"companyId"]);
+ }
+ }
+ else
+ NSLog(@"Could not select ..");
+ }
+
+ /* do some update */
+
+ if ((e = [m entityNamed:@"Person"])) {
+ attrs = [e attributes];
+ q = [[EOSQLQualifier alloc]
+ initWithEntity:e
+ qualifierFormat:@"%A='helge'", @"login"];
+ AUTORELEASE(q);
+
+ if ([ch selectAttributes:attrs
+ describedByQualifier:q
+ fetchOrder:nil
+ lock:NO]) {
+ NSDictionary *record;
+
+ record = [ch fetchAttributes:attrs withZone:nil];
+ }
+ else
+ NSLog(@"Could not select ..");
+ }
+
+ RELEASE(pool);
+ }
+
+ NSLog(@"committing tx ..");
+ if ([ctx commitTransaction])
+ NSLog(@" could commit.");
+ else
+ NSLog(@" commit failed.");
+ }
+
+ NSLog(@"closing channel ..");
+ [ch closeChannel];
+ }
+ }
+ NS_HANDLER {
+ fprintf(stderr, "exception: %s\n", [[localException description] cString]);
+ abort();
+ }
+ NS_ENDHANDLER;
+
+ return 0;
+}
--- /dev/null
+#define BOOLOID 16
+#define BYTEAOID 17
+#define CHAROID 18
+#define NAMEOID 19
+#define INT8OID 20
+#define INT2OID 21
+#define INT2VECTOROID 22
+#define INT4OID 23
+#define REGPROCOID 24
+#define TEXTOID 25
+#define OIDOID 26
+#define TIDOID 27
+#define XIDOID 28
+#define CIDOID 29
+#define OIDVECTOROID 30
+#define POINTOID 600
+#define LSEGOID 601
+#define PATHOID 602
+#define BOXOID 603
+#define POLYGONOID 604
+#define LINEOID 628
+#define FLOAT4OID 700
+#define FLOAT8OID 701
+#define ABSTIMEOID 702
+#define RELTIMEOID 703
+#define TINTERVALOID 704
+#define UNKNOWNOID 705
+#define CIRCLEOID 718
+#define CASHOID 790
+#define MACADDROID 829
+#define INETOID 869
+#define CIDROID 650
+#define ACLITEMSIZE 8
+#define BPCHAROID 1042
+#define VARCHAROID 1043
+#define DATEOID 1082
+#define TIMEOID 1083
+#define TIMESTAMPOID 1114
+#define TIMESTAMPTZOID 1184
+#define INTERVALOID 1186
+#define TIMETZOID 1266
+#define BITOID 1560
+#define VARBITOID 1562
+#define NUMERICOID 1700
+#define REFCURSOROID 1790
--- /dev/null
+{
+ EOModelVersion = 1;
+ adaptorClassName = PostgreSQLAdaptor;
+ adaptorName = PostgreSQL;
+
+ entities = (
+ {
+ name = Doof;
+ externalName = doof;
+ className = EOGenericRecord;
+ primaryKeyAttributes = ( pkey );
+ attributesUsedForLocking = ( pkey );
+ classProperties = ( pkey );
+ attributes = (
+ {
+ valueClassName = NSNumber;
+ columnName = pkey;
+ name = pkey;
+ valueType = i;
+ externalType = INT; // t_id
+ },
+ );
+ }
+ );
+}
--- /dev/null
+
+# type test table
+
+create table pgtypetest (
+ t_int2 int2,
+ t_int4 int4,
+ t_int8 int8,
+ t_int int,
+ t_varchar255 varchar(255),
+ t_datetime datetime,
+ t_timestamp timestamp,
+ t_timestamp_wtz timestamp with time zone
+);
--- /dev/null
+# $Id: Version 1 2004-08-20 10:38:46Z znek $
+#
+# This file is included by library makefiles to set the version information
+# of the executable.
+
+MAJOR_VERSION=1
+MINOR_VERSION=0
+# the SUBMINOR_VERSION is set by the Version file inside of a library project
--- /dev/null
+# $Id: common.make 1 2004-08-20 10:38:46Z znek $
+
+SKYROOT=..
+
+include $(GNUSTEP_MAKEFILES)/common.make
+include $(SKYROOT)/Version
+-include ./Version
+
+GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_LOCAL_ROOT)
+
+ADDITIONAL_CPPFLAGS += -pipe -Wall -Wno-protocol
+
+SOPEDIR="../../../SOPE"
+
+ADDITIONAL_INCLUDE_DIRS += \
+ -I.. \
+ -I$(SOPEDIR)/skyrix-xml \
+ -I$(SOPEDIR)/skyrix-core \
+ -I$(SOPEDIR)/skyrix-core/NGExtensions \
+
+ADDITIONAL_LIB_DIRS += \
+ -L./$(GNUSTEP_OBJ_DIR) \
+ -L$(SOPEDIR)/skyrix-xml/SaxObjC/$(GNUSTEP_OBJ_DIR) \
+ -L$(SOPEDIR)/skyrix-xml/DOM/$(GNUSTEP_OBJ_DIR) \
+ -L$(SOPEDIR)/skyrix-core/EOControl/$(GNUSTEP_OBJ_DIR) \
+ -L$(SOPEDIR)/skyrix-core/NGExtensions/$(GNUSTEP_OBJ_DIR)
+
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 39;
+ objects = {
+ E890B00E055AB18B004301A0 = {
+ children = (
+ E890B01B055AB194004301A0,
+ E890B01D055AB1A0004301A0,
+ E890B01C055AB19B004301A0,
+ E8AC8D0905ABCA5E008C206D,
+ E890B028055AB1B8004301A0,
+ E8AC8D4E05ABCB39008C206D,
+ );
+ isa = PBXGroup;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E890B010055AB18B004301A0 = {
+ buildRules = (
+ );
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ };
+ isa = PBXBuildStyle;
+ name = Development;
+ };
+ E890B011055AB18B004301A0 = {
+ buildRules = (
+ );
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ };
+ isa = PBXBuildStyle;
+ name = Deployment;
+ };
+ E890B012055AB18B004301A0 = {
+ buildSettings = {
+ };
+ buildStyles = (
+ E890B010055AB18B004301A0,
+ E890B011055AB18B004301A0,
+ );
+ hasScannedForEncodings = 1;
+ isa = PBXProject;
+ mainGroup = E890B00E055AB18B004301A0;
+ productRefGroup = E890B028055AB1B8004301A0;
+ projectDirPath = "";
+ targets = (
+ E890B026055AB1B8004301A0,
+ E8AC8D4C05ABCB39008C206D,
+ E8AC8DDC05ABCBC9008C206D,
+ );
+ };
+ E890B01B055AB194004301A0 = {
+ children = (
+ E8AC8BEC05ABC13E008C206D,
+ E8AC8C2005ABC13E008C206D,
+ E8AC8C2205ABC13E008C206D,
+ E8AC8C2305ABC13E008C206D,
+ E8AC8BEF05ABC13E008C206D,
+ E8AC8C5F05ABC179008C206D,
+ E8AC8C6005ABC18A008C206D,
+ E890B02A055AB1C0004301A0,
+ E890B029055AB1BC004301A0,
+ E8AC8CF405ABC67E008C206D,
+ );
+ isa = PBXGroup;
+ name = GDLAccess;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E890B01C055AB19B004301A0 = {
+ children = (
+ );
+ isa = PBXGroup;
+ name = FrontBase2;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E890B01D055AB1A0004301A0 = {
+ children = (
+ E8AC8D1F05ABCAB9008C206D,
+ E8AC8D2205ABCAB9008C206D,
+ E8AC8D2305ABCAB9008C206D,
+ E8AC8D3E05ABCAB9008C206D,
+ E8AC8D4005ABCAB9008C206D,
+ E8AC8D4205ABCAB9008C206D,
+ E8AC8D4505ABCAEA008C206D,
+ E8AC8D4605ABCAFF008C206D,
+ E8AC8D4705ABCB1B008C206D,
+ );
+ isa = PBXGroup;
+ name = PostgreSQL;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E890B022055AB1B8004301A0 = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8C2505ABC13E008C206D,
+ E8AC8C8E05ABC218008C206D,
+ E8AC8C8F05ABC218008C206D,
+ E8AC8C9005ABC218008C206D,
+ E8AC8C9105ABC218008C206D,
+ E8AC8C9205ABC218008C206D,
+ E8AC8C9305ABC218008C206D,
+ E8AC8C9405ABC218008C206D,
+ E8AC8C9505ABC218008C206D,
+ E8AC8C9605ABC218008C206D,
+ E8AC8C9705ABC218008C206D,
+ E8AC8C9805ABC218008C206D,
+ E8AC8C9905ABC218008C206D,
+ E8AC8C9A05ABC218008C206D,
+ E8AC8C9B05ABC218008C206D,
+ E8AC8C9C05ABC218008C206D,
+ E8AC8C9D05ABC218008C206D,
+ E8AC8C9E05ABC218008C206D,
+ E8AC8C9F05ABC218008C206D,
+ E8AC8CA005ABC218008C206D,
+ E8AC8CA105ABC218008C206D,
+ E8AC8CA205ABC218008C206D,
+ E8AC8CA305ABC218008C206D,
+ E8AC8CA405ABC218008C206D,
+ E8AC8CA505ABC218008C206D,
+ E8AC8CA605ABC218008C206D,
+ E8AC8CA705ABC218008C206D,
+ E8AC8CA805ABC218008C206D,
+ E8AC8CA905ABC218008C206D,
+ E8AC8CAA05ABC218008C206D,
+ E8AC8CAB05ABC218008C206D,
+ E8AC8CAC05ABC218008C206D,
+ E8AC8CAD05ABC218008C206D,
+ E8AC8CAE05ABC218008C206D,
+ E8AC8CAF05ABC218008C206D,
+ E8AC8CB005ABC218008C206D,
+ E8AC8CB105ABC218008C206D,
+ E8AC8CB205ABC218008C206D,
+ E8AC8CB305ABC218008C206D,
+ E8AC8CB405ABC218008C206D,
+ E8AC8CB505ABC218008C206D,
+ E8AC8D0105ABC6AE008C206D,
+ E8AC8D0305ABC6AE008C206D,
+ E8AC8D0705ABC6AE008C206D,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E890B023055AB1B8004301A0 = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8C2405ABC13E008C206D,
+ E8AC8C2705ABC13E008C206D,
+ E8AC8C5205ABC13E008C206D,
+ E8AC8C5305ABC13E008C206D,
+ E8AC8C5405ABC13E008C206D,
+ E8AC8C5505ABC13E008C206D,
+ E8AC8C5805ABC13E008C206D,
+ E8AC8C5905ABC13E008C206D,
+ E8AC8C5A05ABC13E008C206D,
+ E8AC8C5B05ABC13E008C206D,
+ E8AC8CFF05ABC6AE008C206D,
+ E8AC8D0005ABC6AE008C206D,
+ E8AC8D0505ABC6AE008C206D,
+ E8AC8D0605ABC6AE008C206D,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E890B024055AB1B8004301A0 = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8C2805ABC13E008C206D,
+ E8AC8C2905ABC13E008C206D,
+ E8AC8C2A05ABC13E008C206D,
+ E8AC8C2B05ABC13E008C206D,
+ E8AC8C2C05ABC13E008C206D,
+ E8AC8C2D05ABC13E008C206D,
+ E8AC8C2E05ABC13E008C206D,
+ E8AC8C2F05ABC13E008C206D,
+ E8AC8C3005ABC13E008C206D,
+ E8AC8C3105ABC13E008C206D,
+ E8AC8C3205ABC13E008C206D,
+ E8AC8C3305ABC13E008C206D,
+ E8AC8C3405ABC13E008C206D,
+ E8AC8C3505ABC13E008C206D,
+ E8AC8C3605ABC13E008C206D,
+ E8AC8C3705ABC13E008C206D,
+ E8AC8C3805ABC13E008C206D,
+ E8AC8C3905ABC13E008C206D,
+ E8AC8C3A05ABC13E008C206D,
+ E8AC8C3B05ABC13E008C206D,
+ E8AC8C3C05ABC13E008C206D,
+ E8AC8C3D05ABC13E008C206D,
+ E8AC8C3E05ABC13E008C206D,
+ E8AC8C3F05ABC13E008C206D,
+ E8AC8C4005ABC13E008C206D,
+ E8AC8C4105ABC13E008C206D,
+ E8AC8C4205ABC13E008C206D,
+ E8AC8C4305ABC13E008C206D,
+ E8AC8C4405ABC13E008C206D,
+ E8AC8C4505ABC13E008C206D,
+ E8AC8C4605ABC13E008C206D,
+ E8AC8C4705ABC13E008C206D,
+ E8AC8C4805ABC13E008C206D,
+ E8AC8C4905ABC13E008C206D,
+ E8AC8C4A05ABC13E008C206D,
+ E8AC8C4B05ABC13E008C206D,
+ E8AC8C4C05ABC13E008C206D,
+ E8AC8C4D05ABC13E008C206D,
+ E8AC8C4E05ABC13E008C206D,
+ E8AC8C4F05ABC13E008C206D,
+ E8AC8C5005ABC13E008C206D,
+ E8AC8C5105ABC13E008C206D,
+ E8AC8C5605ABC13E008C206D,
+ E8AC8C5705ABC13E008C206D,
+ E8AC8D0205ABC6AE008C206D,
+ E8AC8D0405ABC6AE008C206D,
+ E8AC8D0805ABC6AE008C206D,
+ E8D0A07E0605B8D10084DA47,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E890B025055AB1B8004301A0 = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8D0B05ABCA7A008C206D,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E890B026055AB1B8004301A0 = {
+ buildPhases = (
+ E890B022055AB1B8004301A0,
+ E890B023055AB1B8004301A0,
+ E890B024055AB1B8004301A0,
+ E890B025055AB1B8004301A0,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = /Users/helge/build;
+ FRAMEWORK_VERSION = A;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Foundation.framework/Headers/Foundation.h";
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
+ HEADER_SEARCH_PATHS = "/Users/helge/OGo/OpenGroupware.org/ThirdParty/gnustep-db/GDLAccess/";
+ INFOPLIST_FILE = "GDLAccess/GDLAccess-Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ OTHER_CFLAGS = "-DAPPLE_RUNTIME=1 -DNeXT_RUNTIME=1 -DCOCOA_Foundation_LIBRARY=1 -DNeXT_Foundation_LIBRARY=1 -DXCODE_SELF_COMPILE=1";
+ OTHER_LDFLAGS = "-framework Foundation";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = GDLAccess;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = GDLAccess;
+ productName = GDLAccess;
+ productReference = E890B027055AB1B8004301A0;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>GDLAccess</string>
+ <key>CFBundleGetInfoString</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.MySoftwareCompany.GDLAccess</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string></string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0.0d1</string>
+</dict>
+</plist>
+";
+ productType = "com.apple.product-type.framework";
+ };
+ E890B027055AB1B8004301A0 = {
+ explicitFileType = wrapper.framework;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = GDLAccess.framework;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ E890B028055AB1B8004301A0 = {
+ children = (
+ E890B027055AB1B8004301A0,
+ E8AC8D4D05ABCB39008C206D,
+ );
+ isa = PBXGroup;
+ name = Products;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E890B029055AB1BC004301A0 = {
+ children = (
+ E8AC8BED05ABC13E008C206D,
+ E8AC8BF005ABC13E008C206D,
+ E8AC8C6205ABC19C008C206D,
+ E8AC8C6305ABC1B2008C206D,
+ E8AC8C6405ABC1CB008C206D,
+ E8AC8C6505ABC1DB008C206D,
+ E8AC8BF905ABC13E008C206D,
+ E8AC8BFC05ABC13E008C206D,
+ E8AC8C0505ABC13E008C206D,
+ E8AC8C0605ABC13E008C206D,
+ E8AC8C0705ABC13E008C206D,
+ E8AC8C0805ABC13E008C206D,
+ E8AC8C0905ABC13E008C206D,
+ E8AC8C0B05ABC13E008C206D,
+ E8AC8C1005ABC13E008C206D,
+ E8AC8C1205ABC13E008C206D,
+ E8AC8C1605ABC13E008C206D,
+ E8AC8C1F05ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Classes;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E890B02A055AB1C0004301A0 = {
+ children = (
+ E8AC8C6605ABC218008C206D,
+ E8AC8C6705ABC218008C206D,
+ E8AC8C6805ABC218008C206D,
+ E8AC8C6905ABC218008C206D,
+ E8AC8C6A05ABC218008C206D,
+ E8AC8C6B05ABC218008C206D,
+ E8AC8C6C05ABC218008C206D,
+ E8AC8C6D05ABC218008C206D,
+ E8AC8C6E05ABC218008C206D,
+ E8AC8C6F05ABC218008C206D,
+ E8AC8C7005ABC218008C206D,
+ E8AC8C7105ABC218008C206D,
+ E8AC8C7205ABC218008C206D,
+ E8AC8C7305ABC218008C206D,
+ E8AC8C7405ABC218008C206D,
+ E8AC8C7505ABC218008C206D,
+ E8AC8C7605ABC218008C206D,
+ E8AC8C7705ABC218008C206D,
+ E8AC8C7805ABC218008C206D,
+ E8AC8C7905ABC218008C206D,
+ E8AC8C7A05ABC218008C206D,
+ E8AC8C7B05ABC218008C206D,
+ E8AC8C7C05ABC218008C206D,
+ E8AC8C7D05ABC218008C206D,
+ E8AC8C7E05ABC218008C206D,
+ E8AC8C7F05ABC218008C206D,
+ E8AC8C8005ABC218008C206D,
+ E8AC8C8105ABC218008C206D,
+ E8AC8C8205ABC218008C206D,
+ E8AC8C8305ABC218008C206D,
+ E8AC8C8405ABC218008C206D,
+ E8AC8C8505ABC218008C206D,
+ E8AC8C8605ABC218008C206D,
+ E8AC8C8705ABC218008C206D,
+ E8AC8C8805ABC218008C206D,
+ E8AC8C8905ABC218008C206D,
+ E8AC8C8A05ABC218008C206D,
+ E8AC8C8B05ABC218008C206D,
+ E8AC8C8C05ABC218008C206D,
+ E8AC8C8D05ABC218008C206D,
+ );
+ isa = PBXGroup;
+ name = Headers;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BEC05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = ChangeLog;
+ path = GDLAccess/ChangeLog;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BED05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = common.h;
+ path = GDLAccess/common.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BEE05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "connect-EOAdaptor.m";
+ path = "GDLAccess/connect-EOAdaptor.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BEF05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = COPYING.LIB;
+ path = GDLAccess/COPYING.LIB;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF005ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = eoaccess.m;
+ path = GDLAccess/eoaccess.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF105ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAdaptor.m;
+ path = GDLAccess/EOAdaptor.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF205ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAdaptorChannel.m;
+ path = GDLAccess/EOAdaptorChannel.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF305ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOAdaptorChannel+Attributes.m";
+ path = "GDLAccess/EOAdaptorChannel+Attributes.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF405ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAdaptorContext.m;
+ path = GDLAccess/EOAdaptorContext.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF505ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAdaptorDataSource.m;
+ path = GDLAccess/EOAdaptorDataSource.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF605ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAdaptorGlobalID.m;
+ path = GDLAccess/EOAdaptorGlobalID.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF705ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAdaptorOperation.m;
+ path = GDLAccess/EOAdaptorOperation.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF805ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOAndQualifier+SQL.m";
+ path = "GDLAccess/EOAndQualifier+SQL.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BF905ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOArrayProxy.m;
+ path = GDLAccess/EOArrayProxy.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BFA05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAttribute.m;
+ path = GDLAccess/EOAttribute.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BFB05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOAttributeOrdering.m;
+ path = GDLAccess/EOAttributeOrdering.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BFC05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOCustomValues.m;
+ path = GDLAccess/EOCustomValues.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BFD05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EODatabase.m;
+ path = GDLAccess/EODatabase.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BFE05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EODatabaseChannel.m;
+ path = GDLAccess/EODatabaseChannel.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8BFF05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EODatabaseContext.m;
+ path = GDLAccess/EODatabaseContext.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0005ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EODatabaseFault.m;
+ path = GDLAccess/EODatabaseFault.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0105ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EODatabaseFaultResolver.m;
+ path = GDLAccess/EODatabaseFaultResolver.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0205ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOEntity.m;
+ path = GDLAccess/EOEntity.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0305ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOEntity+Factory.m";
+ path = "GDLAccess/EOEntity+Factory.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0405ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOEntityClassDescription.m;
+ path = GDLAccess/EOEntityClassDescription.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0505ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOExpressionArray.m;
+ path = GDLAccess/EOExpressionArray.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0605ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOFault.m;
+ path = GDLAccess/EOFault.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0705ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOFaultHandler.m;
+ path = GDLAccess/EOFaultHandler.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0805ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOFExceptions.m;
+ path = GDLAccess/EOFExceptions.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0905ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOGenericRecord.m;
+ path = GDLAccess/EOGenericRecord.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0A05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOKeyComparisonQualifier+SQL.m";
+ path = "GDLAccess/EOKeyComparisonQualifier+SQL.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0B05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOKeySortOrdering.m;
+ path = GDLAccess/EOKeySortOrdering.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0C05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOKeyValueQualifier+SQL.m";
+ path = "GDLAccess/EOKeyValueQualifier+SQL.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0D05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOModel.m;
+ path = GDLAccess/EOModel.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0E05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOModelGroup.m;
+ path = GDLAccess/EOModelGroup.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C0F05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EONotQualifier+SQL.m";
+ path = "GDLAccess/EONotQualifier+SQL.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1005ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOObjectUniquer.m;
+ path = GDLAccess/EOObjectUniquer.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1105ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOOrQualifier+SQL.m";
+ path = "GDLAccess/EOOrQualifier+SQL.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1205ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOPrimaryKeyDictionary.m;
+ path = GDLAccess/EOPrimaryKeyDictionary.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1305ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOQualifier+SQL.m";
+ path = "GDLAccess/EOQualifier+SQL.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1405ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOQualifierScanner.m;
+ path = GDLAccess/EOQualifierScanner.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1505ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOQuotedExpression.m;
+ path = GDLAccess/EOQuotedExpression.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1605ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EORecordDictionary.m;
+ path = GDLAccess/EORecordDictionary.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1705ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EORelationship.m;
+ path = GDLAccess/EORelationship.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1805ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOSQLExpression.m;
+ path = GDLAccess/EOSQLExpression.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1905ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOSQLQualifier.m;
+ path = GDLAccess/EOSQLQualifier.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1A05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = GNUmakefile;
+ path = GDLAccess/GNUmakefile;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1B05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = GNUmakefile.postamble;
+ path = GDLAccess/GNUmakefile.postamble;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1C05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = GNUmakefile.preamble;
+ path = GDLAccess/GNUmakefile.preamble;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1D05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = libGDLAccess.def;
+ path = GDLAccess/libGDLAccess.def;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1E05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "load-EOAdaptor.m";
+ path = "GDLAccess/load-EOAdaptor.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C1F05ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "NSObject+EONullInit.m";
+ path = "GDLAccess/NSObject+EONullInit.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C2005ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = README;
+ path = GDLAccess/README;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C2105ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text.script.python;
+ name = test.py;
+ path = GDLAccess/test.py;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C2205ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = TODO;
+ path = GDLAccess/TODO;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C2305ABC13E008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = Version;
+ path = GDLAccess/Version;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C2405ABC13E008C206D = {
+ fileRef = E8AC8BEC05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2505ABC13E008C206D = {
+ fileRef = E8AC8BED05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ E8AC8C2705ABC13E008C206D = {
+ fileRef = E8AC8BEF05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2805ABC13E008C206D = {
+ fileRef = E8AC8BF005ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2905ABC13E008C206D = {
+ fileRef = E8AC8BF105ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2A05ABC13E008C206D = {
+ fileRef = E8AC8BF205ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2B05ABC13E008C206D = {
+ fileRef = E8AC8BF305ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2C05ABC13E008C206D = {
+ fileRef = E8AC8BF405ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2D05ABC13E008C206D = {
+ fileRef = E8AC8BF505ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2E05ABC13E008C206D = {
+ fileRef = E8AC8BF605ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C2F05ABC13E008C206D = {
+ fileRef = E8AC8BF705ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3005ABC13E008C206D = {
+ fileRef = E8AC8BF805ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3105ABC13E008C206D = {
+ fileRef = E8AC8BF905ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3205ABC13E008C206D = {
+ fileRef = E8AC8BFA05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3305ABC13E008C206D = {
+ fileRef = E8AC8BFB05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3405ABC13E008C206D = {
+ fileRef = E8AC8BFC05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3505ABC13E008C206D = {
+ fileRef = E8AC8BFD05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3605ABC13E008C206D = {
+ fileRef = E8AC8BFE05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3705ABC13E008C206D = {
+ fileRef = E8AC8BFF05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3805ABC13E008C206D = {
+ fileRef = E8AC8C0005ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3905ABC13E008C206D = {
+ fileRef = E8AC8C0105ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3A05ABC13E008C206D = {
+ fileRef = E8AC8C0205ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3B05ABC13E008C206D = {
+ fileRef = E8AC8C0305ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3C05ABC13E008C206D = {
+ fileRef = E8AC8C0405ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3D05ABC13E008C206D = {
+ fileRef = E8AC8C0505ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3E05ABC13E008C206D = {
+ fileRef = E8AC8C0605ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C3F05ABC13E008C206D = {
+ fileRef = E8AC8C0705ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4005ABC13E008C206D = {
+ fileRef = E8AC8C0805ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4105ABC13E008C206D = {
+ fileRef = E8AC8C0905ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4205ABC13E008C206D = {
+ fileRef = E8AC8C0A05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4305ABC13E008C206D = {
+ fileRef = E8AC8C0B05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4405ABC13E008C206D = {
+ fileRef = E8AC8C0C05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4505ABC13E008C206D = {
+ fileRef = E8AC8C0D05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4605ABC13E008C206D = {
+ fileRef = E8AC8C0E05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4705ABC13E008C206D = {
+ fileRef = E8AC8C0F05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4805ABC13E008C206D = {
+ fileRef = E8AC8C1005ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4905ABC13E008C206D = {
+ fileRef = E8AC8C1105ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4A05ABC13E008C206D = {
+ fileRef = E8AC8C1205ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4B05ABC13E008C206D = {
+ fileRef = E8AC8C1305ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4C05ABC13E008C206D = {
+ fileRef = E8AC8C1405ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4D05ABC13E008C206D = {
+ fileRef = E8AC8C1505ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4E05ABC13E008C206D = {
+ fileRef = E8AC8C1605ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C4F05ABC13E008C206D = {
+ fileRef = E8AC8C1705ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5005ABC13E008C206D = {
+ fileRef = E8AC8C1805ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5105ABC13E008C206D = {
+ fileRef = E8AC8C1905ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5205ABC13E008C206D = {
+ fileRef = E8AC8C1A05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5305ABC13E008C206D = {
+ fileRef = E8AC8C1B05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5405ABC13E008C206D = {
+ fileRef = E8AC8C1C05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5505ABC13E008C206D = {
+ fileRef = E8AC8C1D05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5605ABC13E008C206D = {
+ fileRef = E8AC8C1E05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5705ABC13E008C206D = {
+ fileRef = E8AC8C1F05ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5805ABC13E008C206D = {
+ fileRef = E8AC8C2005ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5905ABC13E008C206D = {
+ fileRef = E8AC8C2105ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5A05ABC13E008C206D = {
+ fileRef = E8AC8C2205ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5B05ABC13E008C206D = {
+ fileRef = E8AC8C2305ABC13E008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8C5F05ABC179008C206D = {
+ children = (
+ E8AC8C1A05ABC13E008C206D,
+ E8AC8C1B05ABC13E008C206D,
+ E8AC8C1C05ABC13E008C206D,
+ E8AC8C1D05ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Makefiles;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6005ABC18A008C206D = {
+ children = (
+ E8AC8C2105ABC13E008C206D,
+ E8AC8BEE05ABC13E008C206D,
+ E8AC8C1E05ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Tools;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6205ABC19C008C206D = {
+ children = (
+ E8AC8BF105ABC13E008C206D,
+ E8AC8BF205ABC13E008C206D,
+ E8AC8BF305ABC13E008C206D,
+ E8AC8BF405ABC13E008C206D,
+ E8AC8BF505ABC13E008C206D,
+ E8AC8BF605ABC13E008C206D,
+ E8AC8BF705ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Adaptor;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6305ABC1B2008C206D = {
+ children = (
+ E8AC8BF805ABC13E008C206D,
+ E8AC8C0A05ABC13E008C206D,
+ E8AC8C0C05ABC13E008C206D,
+ E8AC8C0F05ABC13E008C206D,
+ E8AC8C1105ABC13E008C206D,
+ E8AC8C1305ABC13E008C206D,
+ E8AC8C1405ABC13E008C206D,
+ E8AC8C1505ABC13E008C206D,
+ E8AC8C1805ABC13E008C206D,
+ E8D0A07D0605B8D10084DA47,
+ E8AC8C1905ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Qualifier;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6405ABC1CB008C206D = {
+ children = (
+ E8AC8BFA05ABC13E008C206D,
+ E8AC8BFB05ABC13E008C206D,
+ E8AC8C0205ABC13E008C206D,
+ E8AC8C0305ABC13E008C206D,
+ E8AC8C0405ABC13E008C206D,
+ E8AC8C0D05ABC13E008C206D,
+ E8AC8C0E05ABC13E008C206D,
+ E8AC8C1705ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Model;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6505ABC1DB008C206D = {
+ children = (
+ E8AC8BFD05ABC13E008C206D,
+ E8AC8BFE05ABC13E008C206D,
+ E8AC8BFF05ABC13E008C206D,
+ E8AC8C0005ABC13E008C206D,
+ E8AC8C0105ABC13E008C206D,
+ );
+ isa = PBXGroup;
+ name = Database;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6605ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAccess.h;
+ path = GDLAccess/EOAccess/EOAccess.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6705ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAdaptor.h;
+ path = GDLAccess/EOAccess/EOAdaptor.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6805ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAdaptorChannel.h;
+ path = GDLAccess/EOAccess/EOAdaptorChannel.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6905ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = "EOAdaptorChannel+Attributes.h";
+ path = "GDLAccess/EOAccess/EOAdaptorChannel+Attributes.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6A05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAdaptorContext.h;
+ path = GDLAccess/EOAccess/EOAdaptorContext.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6B05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAdaptorDataSource.h;
+ path = GDLAccess/EOAccess/EOAdaptorDataSource.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6C05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAdaptorGlobalID.h;
+ path = GDLAccess/EOAccess/EOAdaptorGlobalID.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6D05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAdaptorOperation.h;
+ path = GDLAccess/EOAccess/EOAdaptorOperation.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6E05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOArrayProxy.h;
+ path = GDLAccess/EOAccess/EOArrayProxy.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C6F05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAttribute.h;
+ path = GDLAccess/EOAccess/EOAttribute.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7005ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOAttributeOrdering.h;
+ path = GDLAccess/EOAccess/EOAttributeOrdering.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7105ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOCustomValues.h;
+ path = GDLAccess/EOAccess/EOCustomValues.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7205ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EODatabase.h;
+ path = GDLAccess/EOAccess/EODatabase.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7305ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EODatabaseChannel.h;
+ path = GDLAccess/EOAccess/EODatabaseChannel.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7405ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EODatabaseContext.h;
+ path = GDLAccess/EOAccess/EODatabaseContext.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7505ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EODatabaseFault.h;
+ path = GDLAccess/EOAccess/EODatabaseFault.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7605ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EODatabaseFaultResolver.h;
+ path = GDLAccess/EOAccess/EODatabaseFaultResolver.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7705ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EODelegateResponse.h;
+ path = GDLAccess/EOAccess/EODelegateResponse.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7805ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOEntity.h;
+ path = GDLAccess/EOAccess/EOEntity.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7905ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = "EOEntity+Factory.h";
+ path = "GDLAccess/EOAccess/EOEntity+Factory.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7A05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOExpressionArray.h;
+ path = GDLAccess/EOAccess/EOExpressionArray.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7B05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOFault.h;
+ path = GDLAccess/EOAccess/EOFault.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7C05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOFaultHandler.h;
+ path = GDLAccess/EOAccess/EOFaultHandler.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7D05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOFExceptions.h;
+ path = GDLAccess/EOAccess/EOFExceptions.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7E05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOGenericRecord.h;
+ path = GDLAccess/EOAccess/EOGenericRecord.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C7F05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOJoinTypes.h;
+ path = GDLAccess/EOAccess/EOJoinTypes.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8005ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOKeySortOrdering.h;
+ path = GDLAccess/EOAccess/EOKeySortOrdering.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8105ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOModel.h;
+ path = GDLAccess/EOAccess/EOModel.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8205ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOModelGroup.h;
+ path = GDLAccess/EOAccess/EOModelGroup.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8305ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EONull.h;
+ path = GDLAccess/EOAccess/EONull.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8405ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOObjectUniquer.h;
+ path = GDLAccess/EOAccess/EOObjectUniquer.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8505ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOPrimaryKeyDictionary.h;
+ path = GDLAccess/EOAccess/EOPrimaryKeyDictionary.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8605ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOQualifierScanner.h;
+ path = GDLAccess/EOAccess/EOQualifierScanner.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8705ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOQuotedExpression.h;
+ path = GDLAccess/EOAccess/EOQuotedExpression.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8805ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EORecordDictionary.h;
+ path = GDLAccess/EOAccess/EORecordDictionary.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8905ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EORelationship.h;
+ path = GDLAccess/EOAccess/EORelationship.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8A05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOSQLExpression.h;
+ path = GDLAccess/EOAccess/EOSQLExpression.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8B05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = EOSQLQualifier.h;
+ path = GDLAccess/EOAccess/EOSQLQualifier.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8C05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = GDLAccess.h;
+ path = GDLAccess/EOAccess/GDLAccess.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8D05ABC218008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = "NSObject+EONullInit.h";
+ path = "GDLAccess/EOAccess/NSObject+EONullInit.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8C8E05ABC218008C206D = {
+ fileRef = E8AC8C6605ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C8F05ABC218008C206D = {
+ fileRef = E8AC8C6705ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9005ABC218008C206D = {
+ fileRef = E8AC8C6805ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9105ABC218008C206D = {
+ fileRef = E8AC8C6905ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9205ABC218008C206D = {
+ fileRef = E8AC8C6A05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9305ABC218008C206D = {
+ fileRef = E8AC8C6B05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9405ABC218008C206D = {
+ fileRef = E8AC8C6C05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9505ABC218008C206D = {
+ fileRef = E8AC8C6D05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9605ABC218008C206D = {
+ fileRef = E8AC8C6E05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9705ABC218008C206D = {
+ fileRef = E8AC8C6F05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9805ABC218008C206D = {
+ fileRef = E8AC8C7005ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9905ABC218008C206D = {
+ fileRef = E8AC8C7105ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9A05ABC218008C206D = {
+ fileRef = E8AC8C7205ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9B05ABC218008C206D = {
+ fileRef = E8AC8C7305ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9C05ABC218008C206D = {
+ fileRef = E8AC8C7405ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9D05ABC218008C206D = {
+ fileRef = E8AC8C7505ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9E05ABC218008C206D = {
+ fileRef = E8AC8C7605ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8C9F05ABC218008C206D = {
+ fileRef = E8AC8C7705ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA005ABC218008C206D = {
+ fileRef = E8AC8C7805ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA105ABC218008C206D = {
+ fileRef = E8AC8C7905ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA205ABC218008C206D = {
+ fileRef = E8AC8C7A05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA305ABC218008C206D = {
+ fileRef = E8AC8C7B05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA405ABC218008C206D = {
+ fileRef = E8AC8C7C05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA505ABC218008C206D = {
+ fileRef = E8AC8C7D05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA605ABC218008C206D = {
+ fileRef = E8AC8C7E05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA705ABC218008C206D = {
+ fileRef = E8AC8C7F05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA805ABC218008C206D = {
+ fileRef = E8AC8C8005ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CA905ABC218008C206D = {
+ fileRef = E8AC8C8105ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CAA05ABC218008C206D = {
+ fileRef = E8AC8C8205ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CAB05ABC218008C206D = {
+ fileRef = E8AC8C8305ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CAC05ABC218008C206D = {
+ fileRef = E8AC8C8405ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CAD05ABC218008C206D = {
+ fileRef = E8AC8C8505ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CAE05ABC218008C206D = {
+ fileRef = E8AC8C8605ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CAF05ABC218008C206D = {
+ fileRef = E8AC8C8705ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CB005ABC218008C206D = {
+ fileRef = E8AC8C8805ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CB105ABC218008C206D = {
+ fileRef = E8AC8C8905ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CB205ABC218008C206D = {
+ fileRef = E8AC8C8A05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CB305ABC218008C206D = {
+ fileRef = E8AC8C8B05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CB405ABC218008C206D = {
+ fileRef = E8AC8C8C05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CB505ABC218008C206D = {
+ fileRef = E8AC8C8D05ABC218008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ E8AC8CF405ABC67E008C206D = {
+ children = (
+ E8AC8CF505ABC6AE008C206D,
+ E8AC8CF605ABC6AE008C206D,
+ E8AC8CFB05ABC6AE008C206D,
+ E8AC8CFC05ABC6AE008C206D,
+ E8AC8CF705ABC6AE008C206D,
+ E8AC8CF805ABC6AE008C206D,
+ E8AC8CF905ABC6AE008C206D,
+ E8AC8CFA05ABC6AE008C206D,
+ E8AC8CFD05ABC6AE008C206D,
+ E8AC8CFE05ABC6AE008C206D,
+ );
+ isa = PBXGroup;
+ name = FoundationExt;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CF505ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = COPYING;
+ path = GDLAccess/FoundationExt/COPYING;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CF605ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = COPYRIGHT;
+ path = GDLAccess/FoundationExt/COPYRIGHT;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CF705ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = DefaultScannerHandler.h;
+ path = GDLAccess/FoundationExt/DefaultScannerHandler.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CF805ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = DefaultScannerHandler.m;
+ path = GDLAccess/FoundationExt/DefaultScannerHandler.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CF905ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = FormatScanner.h;
+ path = GDLAccess/FoundationExt/FormatScanner.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CFA05ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = FormatScanner.m;
+ path = GDLAccess/FoundationExt/FormatScanner.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CFB05ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = GNUmakefile;
+ path = GDLAccess/FoundationExt/GNUmakefile;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CFC05ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = LICENSE;
+ path = GDLAccess/FoundationExt/LICENSE;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CFD05ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PrintfFormatScanner.h;
+ path = GDLAccess/FoundationExt/PrintfFormatScanner.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CFE05ABC6AE008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PrintfFormatScanner.m;
+ path = GDLAccess/FoundationExt/PrintfFormatScanner.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8CFF05ABC6AE008C206D = {
+ fileRef = E8AC8CF505ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0005ABC6AE008C206D = {
+ fileRef = E8AC8CF605ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0105ABC6AE008C206D = {
+ fileRef = E8AC8CF705ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0205ABC6AE008C206D = {
+ fileRef = E8AC8CF805ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0305ABC6AE008C206D = {
+ fileRef = E8AC8CF905ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0405ABC6AE008C206D = {
+ fileRef = E8AC8CFA05ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0505ABC6AE008C206D = {
+ fileRef = E8AC8CFB05ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0605ABC6AE008C206D = {
+ fileRef = E8AC8CFC05ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0705ABC6AE008C206D = {
+ fileRef = E8AC8CFD05ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0805ABC6AE008C206D = {
+ fileRef = E8AC8CFE05ABC6AE008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D0905ABCA5E008C206D = {
+ children = (
+ E8AC8D0A05ABCA7A008C206D,
+ );
+ isa = PBXGroup;
+ name = "Linked Frameworks";
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D0A05ABCA7A008C206D = {
+ isa = PBXFileReference;
+ lastKnownFileType = file;
+ name = EOControl.framework;
+ path = /Users/helge/Library/Frameworks/EOControl.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ E8AC8D0B05ABCA7A008C206D = {
+ fileRef = E8AC8D0A05ABCA7A008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8D1F05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = ChangeLog;
+ path = PostgreSQL72/ChangeLog;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2005ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = common.h;
+ path = PostgreSQL72/common.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2105ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist;
+ name = condict.plist;
+ path = PostgreSQL72/condict.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2205ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = COPYING;
+ path = PostgreSQL72/COPYING;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2305ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = COPYING.LIB;
+ path = PostgreSQL72/COPYING.LIB;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2405ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = "EOAttribute+PostgreSQL72.h";
+ path = "PostgreSQL72/EOAttribute+PostgreSQL72.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2505ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "EOAttribute+PostgreSQL72.m";
+ path = "PostgreSQL72/EOAttribute+PostgreSQL72.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2605ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = gdltest.m;
+ path = PostgreSQL72/gdltest.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2705ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = GNUmakefile;
+ path = PostgreSQL72/GNUmakefile;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2805ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = GNUmakefile.preamble;
+ path = PostgreSQL72/GNUmakefile.preamble;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2905ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "NSCalendarDate+PGVal.m";
+ path = "PostgreSQL72/NSCalendarDate+PGVal.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2A05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "NSData+PGVal.m";
+ path = "PostgreSQL72/NSData+PGVal.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2B05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "NSNumber+PGVal.m";
+ path = "PostgreSQL72/NSNumber+PGVal.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2C05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "NSString+PGVal.m";
+ path = "PostgreSQL72/NSString+PGVal.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2D05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = "NSString+PostgreSQL72.h";
+ path = "PostgreSQL72/NSString+PostgreSQL72.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2E05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "NSString+PostgreSQL72.m";
+ path = "PostgreSQL72/NSString+PostgreSQL72.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D2F05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = postgres_types.h;
+ path = PostgreSQL72/postgres_types.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3005ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PostgreSQL72Adaptor.h;
+ path = PostgreSQL72/PostgreSQL72Adaptor.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3105ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PostgreSQL72Adaptor.m;
+ path = PostgreSQL72/PostgreSQL72Adaptor.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3205ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PostgreSQL72Channel.h;
+ path = PostgreSQL72/PostgreSQL72Channel.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3305ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PostgreSQL72Channel.m;
+ path = PostgreSQL72/PostgreSQL72Channel.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3405ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = "PostgreSQL72Channel+Model.h";
+ path = "PostgreSQL72/PostgreSQL72Channel+Model.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3505ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = "PostgreSQL72Channel+Model.m";
+ path = "PostgreSQL72/PostgreSQL72Channel+Model.m";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3605ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PostgreSQL72Context.h;
+ path = PostgreSQL72/PostgreSQL72Context.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3705ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PostgreSQL72Context.m;
+ path = PostgreSQL72/PostgreSQL72Context.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3805ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PostgreSQL72Exception.h;
+ path = PostgreSQL72/PostgreSQL72Exception.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3905ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PostgreSQL72Exception.m;
+ path = PostgreSQL72/PostgreSQL72Exception.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3A05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PostgreSQL72Expression.h;
+ path = PostgreSQL72/PostgreSQL72Expression.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3B05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PostgreSQL72Expression.m;
+ path = PostgreSQL72/PostgreSQL72Expression.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3C05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = PostgreSQL72Values.h;
+ path = PostgreSQL72/PostgreSQL72Values.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3D05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = PostgreSQL72Values.m;
+ path = PostgreSQL72/PostgreSQL72Values.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3E05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = README;
+ path = PostgreSQL72/README;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D3F05ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = test.eomodel;
+ path = PostgreSQL72/test.eomodel;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4005ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = TODO;
+ path = PostgreSQL72/TODO;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4105ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = types.psql;
+ path = PostgreSQL72/types.psql;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4205ABCAB9008C206D = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ name = Version;
+ path = PostgreSQL72/Version;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4305ABCACA008C206D = {
+ children = (
+ E8AC8D3205ABCAB9008C206D,
+ E8AC8D3305ABCAB9008C206D,
+ E8AC8D3405ABCAB9008C206D,
+ E8AC8D3505ABCAB9008C206D,
+ );
+ isa = PBXGroup;
+ name = Channel;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4405ABCADA008C206D = {
+ children = (
+ E8AC8D3C05ABCAB9008C206D,
+ E8AC8D3D05ABCAB9008C206D,
+ E8AC8D2905ABCAB9008C206D,
+ E8AC8D2A05ABCAB9008C206D,
+ E8AC8D2B05ABCAB9008C206D,
+ E8AC8D2C05ABCAB9008C206D,
+ );
+ isa = PBXGroup;
+ name = Values;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4505ABCAEA008C206D = {
+ children = (
+ E8AC8D2705ABCAB9008C206D,
+ E8AC8D2805ABCAB9008C206D,
+ );
+ isa = PBXGroup;
+ name = Makefiles;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4605ABCAFF008C206D = {
+ children = (
+ E8AC8D2105ABCAB9008C206D,
+ E8AC8D2605ABCAB9008C206D,
+ E8AC8D3F05ABCAB9008C206D,
+ E8AC8D4105ABCAB9008C206D,
+ );
+ isa = PBXGroup;
+ name = Misc;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4705ABCB1B008C206D = {
+ children = (
+ E8AC8D2005ABCAB9008C206D,
+ E8AC8D4405ABCADA008C206D,
+ E8AC8D4305ABCACA008C206D,
+ E8AC8D2405ABCAB9008C206D,
+ E8AC8D2505ABCAB9008C206D,
+ E8AC8D2D05ABCAB9008C206D,
+ E8AC8D2E05ABCAB9008C206D,
+ E8AC8D2F05ABCAB9008C206D,
+ E8AC8D3005ABCAB9008C206D,
+ E8AC8D3105ABCAB9008C206D,
+ E8AC8D3605ABCAB9008C206D,
+ E8AC8D3705ABCAB9008C206D,
+ E8AC8D3805ABCAB9008C206D,
+ E8AC8D3905ABCAB9008C206D,
+ E8AC8D3A05ABCAB9008C206D,
+ E8AC8D3B05ABCAB9008C206D,
+ );
+ isa = PBXGroup;
+ name = Classes;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8AC8D4805ABCB39008C206D = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8DC005ABCB8D008C206D,
+ E8AC8DC205ABCB91008C206D,
+ E8AC8DC805ABCB99008C206D,
+ E8AC8DCA05ABCB9C008C206D,
+ E8AC8DCB05ABCB9C008C206D,
+ E8AC8DCD05ABCB9E008C206D,
+ E8AC8DCF05ABCB9F008C206D,
+ E8AC8DD105ABCBA0008C206D,
+ E8AC8DD305ABCBA3008C206D,
+ E8AC8DD505ABCBA4008C206D,
+ E8AC8DD705ABCBA6008C206D,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E8AC8D4905ABCB39008C206D = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8DBF05ABCB8C008C206D,
+ E8AC8DC105ABCB90008C206D,
+ E8AC8DD905ABCBA7008C206D,
+ E8AC8DDA05ABCBAB008C206D,
+ E8AC8DDB05ABCBAC008C206D,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E8AC8D4A05ABCB39008C206D = {
+ buildActionMask = 2147483647;
+ files = (
+ E8AC8DC305ABCB92008C206D,
+ E8AC8DC405ABCB95008C206D,
+ E8AC8DC505ABCB97008C206D,
+ E8AC8DC605ABCB97008C206D,
+ E8AC8DC705ABCB98008C206D,
+ E8AC8DC905ABCB99008C206D,
+ E8AC8DCC05ABCB9D008C206D,
+ E8AC8DCE05ABCB9E008C206D,
+ E8AC8DD005ABCB9F008C206D,
+ E8AC8DD205ABCBA2008C206D,
+ E8AC8DD405ABCBA4008C206D,
+ E8AC8DD605ABCBA5008C206D,
+ E8AC8DD805ABCBA6008C206D,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E8AC8D4B05ABCB39008C206D = {
+ buildActionMask = 2147483647;
+ files = (
+ E8F046BF067385960069C17E,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E8AC8D4C05ABCB39008C206D = {
+ buildPhases = (
+ E8AC8D4805ABCB39008C206D,
+ E8AC8D4905ABCB39008C206D,
+ E8AC8D4A05ABCB39008C206D,
+ E8AC8D4B05ABCB39008C206D,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Foundation.framework/Headers/Foundation.h";
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = NO;
+ HEADER_SEARCH_PATHS = /usr/local/pgsql/include;
+ INFOPLIST_FILE = "PostgreSQL72/PostgreSQL72-Info.plist";
+ INSTALL_PATH = "$(USER_LIBRARY_DIR)/GDLAdaptors/";
+ OTHER_CFLAGS = "-DAPPLE_RUNTIME=1 -DNeXT_RUNTIME=1 -DCOCOA_Foundation_LIBRARY=1 -DNeXT_Foundation_LIBRARY=1";
+ OTHER_LDFLAGS = "-framework Foundation -L/usr/local/pgsql/lib -lpq -lssl -lcrypto";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = PostgreSQL72;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost";
+ WRAPPER_EXTENSION = gdladaptor;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = PostgreSQL72;
+ productName = PostgreSQL72;
+ productReference = E8AC8D4D05ABCB39008C206D;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>PostgreSQL72</string>
+ <key>CFBundleGetInfoString</key>
+ <string></string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.MySoftwareCompany.PostgreSQL72</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string></string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0.0d1</string>
+</dict>
+</plist>
+";
+ productType = "com.apple.product-type.bundle";
+ };
+ E8AC8D4D05ABCB39008C206D = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = PostgreSQL72.gdladaptor;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ E8AC8D4E05ABCB39008C206D = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.xml;
+ name = "PostgreSQL72-Info.plist";
+ path = "PostgreSQL72/PostgreSQL72-Info.plist";
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ E8AC8DBF05ABCB8C008C206D = {
+ fileRef = E8AC8D1F05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC005ABCB8D008C206D = {
+ fileRef = E8AC8D2005ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC105ABCB90008C206D = {
+ fileRef = E8AC8D2305ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC205ABCB91008C206D = {
+ fileRef = E8AC8D2405ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC305ABCB92008C206D = {
+ fileRef = E8AC8D2505ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC405ABCB95008C206D = {
+ fileRef = E8AC8D2905ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC505ABCB97008C206D = {
+ fileRef = E8AC8D2A05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC605ABCB97008C206D = {
+ fileRef = E8AC8D2B05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC705ABCB98008C206D = {
+ fileRef = E8AC8D2C05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC805ABCB99008C206D = {
+ fileRef = E8AC8D2D05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DC905ABCB99008C206D = {
+ fileRef = E8AC8D2E05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DCA05ABCB9C008C206D = {
+ fileRef = E8AC8D2F05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DCB05ABCB9C008C206D = {
+ fileRef = E8AC8D3005ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DCC05ABCB9D008C206D = {
+ fileRef = E8AC8D3105ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DCD05ABCB9E008C206D = {
+ fileRef = E8AC8D3405ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DCE05ABCB9E008C206D = {
+ fileRef = E8AC8D3505ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DCF05ABCB9F008C206D = {
+ fileRef = E8AC8D3205ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD005ABCB9F008C206D = {
+ fileRef = E8AC8D3305ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD105ABCBA0008C206D = {
+ fileRef = E8AC8D3605ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD205ABCBA2008C206D = {
+ fileRef = E8AC8D3705ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD305ABCBA3008C206D = {
+ fileRef = E8AC8D3805ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD405ABCBA4008C206D = {
+ fileRef = E8AC8D3905ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD505ABCBA4008C206D = {
+ fileRef = E8AC8D3A05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD605ABCBA5008C206D = {
+ fileRef = E8AC8D3B05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD705ABCBA6008C206D = {
+ fileRef = E8AC8D3C05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD805ABCBA6008C206D = {
+ fileRef = E8AC8D3D05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DD905ABCBA7008C206D = {
+ fileRef = E8AC8D3E05ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DDA05ABCBAB008C206D = {
+ fileRef = E8AC8D4205ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DDB05ABCBAC008C206D = {
+ fileRef = E8AC8D4005ABCAB9008C206D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8AC8DDC05ABCBC9008C206D = {
+ buildPhases = (
+ );
+ buildSettings = {
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = all;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ E8AC8DDE05ABCBD0008C206D,
+ E8AC8DE005ABCBD0008C206D,
+ );
+ isa = PBXAggregateTarget;
+ name = all;
+ productName = all;
+ };
+ E8AC8DDD05ABCBD0008C206D = {
+ containerPortal = E890B012055AB18B004301A0;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = E890B026055AB1B8004301A0;
+ remoteInfo = GDLAccess;
+ };
+ E8AC8DDE05ABCBD0008C206D = {
+ isa = PBXTargetDependency;
+ target = E890B026055AB1B8004301A0;
+ targetProxy = E8AC8DDD05ABCBD0008C206D;
+ };
+ E8AC8DDF05ABCBD0008C206D = {
+ containerPortal = E890B012055AB18B004301A0;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = E8AC8D4C05ABCB39008C206D;
+ remoteInfo = PostgreSQL72;
+ };
+ E8AC8DE005ABCBD0008C206D = {
+ isa = PBXTargetDependency;
+ target = E8AC8D4C05ABCB39008C206D;
+ targetProxy = E8AC8DDF05ABCBD0008C206D;
+ };
+ E8D0A07D0605B8D10084DA47 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = EOSelectSQLExpression.m;
+ path = GDLAccess/EOSelectSQLExpression.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ E8D0A07E0605B8D10084DA47 = {
+ fileRef = E8D0A07D0605B8D10084DA47;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ E8F046BF067385960069C17E = {
+ fileRef = E890B027055AB1B8004301A0;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ };
+ rootObject = E890B012055AB18B004301A0;
+}
--- /dev/null
+include $(GNUSTEP_MAKEFILES)/common.make
+
+PACKAGE_NAME=sope-ical
+VERSION=4.3.0
+
+SUBPROJECTS = \
+ iCalSaxDriver \
+ NGiCal
+
+include $(GNUSTEP_MAKEFILES)/aggregate.make
2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+ * moved to sope-ical
+
* moved to SOPE 4.3 (v4.3.25)
2004-08-14 Helge Hess <helge.hess@opengroupware.org>
+2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+
+ * moved from sope-xml to sope-ical (v4.3.9)
+
2004-07-02 Helge Hess <helge.hess@opengroupware.org>
* ICalSaxParser.m: added default 'iCalSaxDriverDebugEnabled' to enable
--- /dev/null
+# $Id$
+
+SUBMINOR_VERSION:=9
--- /dev/null
+include $(GNUSTEP_MAKEFILES)/common.make
+
+PACKAGE_NAME=sope-ldap
+VERSION=4.3.0
+
+SUBPROJECTS = \
+ NGLdap \
+
+include $(GNUSTEP_MAKEFILES)/aggregate.make
2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+ * moved to sope-ldap
+
* moved to SOPE 4.3 (v4.3.18)
2004-06-20 Florian G. Pflug <fgp@phlo.org>
--- /dev/null
+include $(GNUSTEP_MAKEFILES)/common.make
+
+PACKAGE_NAME=sope-mime
+VERSION=4.3.0
+
+SUBPROJECTS = \
+ NGMime
+
+include $(GNUSTEP_MAKEFILES)/aggregate.make
2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+ * moved to sope-mime top
+
* moved to SOPE 4.3 (v4.3.172)
2004-08-02 Frank Reppin <frank@opengroupware.org>
--- /dev/null
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+2004-08-20 Helge Hess <helge.hess@opengroupware.org>
+
+ * moved iCalSaxDriver to sope-ical
+
+ * moved ExpatSaxDriver, CFXMLSaxDriver to Recycler
+
+ * moved PlistSaxDriver to samples
+
2004-08-03 Marcus Mueller <znek@mulle-kybernetik.com>
- * SxXML.xcode: fixed missing SaxObjC build dependency. libxmlSAXDriver is
- now built before SaxObjC, so copying it in the framework's wrapper will
- succeed.
+ * SxXML.xcode: fixed missing SaxObjC build dependency. libxmlSAXDriver
+ is now built before SaxObjC, so copying it in the framework's
+ wrapper will succeed.
2004-07-21 Marcus Mueller <znek@mulle-kybernetik.com>
include $(GNUSTEP_MAKEFILES)/common.make
-PACKAGE_NAME=skyrix-xml
-VERSION=4.2.0
+PACKAGE_NAME=sope-xml
+VERSION=4.3.0
SUBPROJECTS = \
SaxObjC \
XmlRpc \
samples \
-ifeq ($(FOUNDATION_LIB), apple)
-# no makefile yet: SUBPROJECTS += CFXMLSaxDriver
-endif
-
include $(GNUSTEP_MAKEFILES)/aggregate.make
+++ /dev/null
-# $Id$
-
-SUBMINOR_VERSION:=8