libgda r3075 - in trunk: . doc/C doc/C/tmpl libgda libgda/sqlite po providers/postgres providers/skel-implementation/capi providers/sqlite tests/data-models tests/meta-store tests/providers tools



Author: vivien
Date: Wed Mar 12 21:18:24 2008
New Revision: 3075
URL: http://svn.gnome.org/viewvc/libgda?rev=3075&view=rev

Log:
2008-03-12  Vivien Malerba <malerba gnome-db org>

	* tools/command-exec.c:
	* tools/gda-sql.c:
	* libgda/gda-meta-struct.[ch]: improvements (to compute only the necessary features, and others)
	* doc/C: doc. updates
	* po/POTFILES.in:
	* po/POTFILES.skip: applied corrections (as proposed by
	http://l10n.gnome.org/module/libgda)
	* libgda/gda-easy.c: applied correction for gda_drop_table() (from Phil Longstaff)
	* libgda/sqlite/gda-sqlite-provider.c: don't count the number of opened connections
	* libgda/gda-meta-struct.[ch]:
	* libgda/gda-meta-store.[ch]: added new methods
	* tests/providers: changed tests to avoid needing reference XML files
	* tools/gda-sql.c: allow to display a graph for a table and the tables it references (by
	appending a '=' after that table name)
	* others: misc. corrections


Removed:
   trunk/tests/providers/FIELDS_SCHEMA_Berkeley-DB_data.xml
   trunk/tests/providers/FIELDS_SCHEMA_Mdb_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_Mdb_film.xml
   trunk/tests/providers/FIELDS_SCHEMA_Mdb_film_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_Mdb_language.xml
   trunk/tests/providers/FIELDS_SCHEMA_MySQL_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_MySQL_film.xml
   trunk/tests/providers/FIELDS_SCHEMA_MySQL_film_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_MySQL_language.xml
   trunk/tests/providers/FIELDS_SCHEMA_PostgreSQL_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_PostgreSQL_film.xml
   trunk/tests/providers/FIELDS_SCHEMA_PostgreSQL_film_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_PostgreSQL_language.xml
   trunk/tests/providers/FIELDS_SCHEMA_SQLite_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_SQLite_film.xml
   trunk/tests/providers/FIELDS_SCHEMA_SQLite_film_actor.xml
   trunk/tests/providers/FIELDS_SCHEMA_SQLite_language.xml
Modified:
   trunk/ChangeLog
   trunk/doc/C/information_schema.png
   trunk/doc/C/information_schema.svg
   trunk/doc/C/libgda-4.0-sections.txt
   trunk/doc/C/libgda-4.0.types.in
   trunk/doc/C/tmpl/gda-batch.sgml
   trunk/doc/C/tmpl/gda-meta-store.sgml
   trunk/doc/C/tmpl/gda-meta-struct.sgml
   trunk/doc/C/tmpl/gda-server-provider.sgml
   trunk/libgda/gda-batch.c
   trunk/libgda/gda-config.c
   trunk/libgda/gda-connection.c
   trunk/libgda/gda-connection.h
   trunk/libgda/gda-data-model-import.c
   trunk/libgda/gda-data-model.c
   trunk/libgda/gda-decl.h
   trunk/libgda/gda-easy.c
   trunk/libgda/gda-marshal.list
   trunk/libgda/gda-meta-store.c
   trunk/libgda/gda-meta-store.h
   trunk/libgda/gda-meta-struct.c
   trunk/libgda/gda-meta-struct.h
   trunk/libgda/gda-server-operation.c
   trunk/libgda/gda-server-provider.h
   trunk/libgda/gda-value.c
   trunk/libgda/information_schema.xml
   trunk/libgda/libgda-array.dtd
   trunk/libgda/sqlite/gda-sqlite-meta.c
   trunk/libgda/sqlite/gda-sqlite-meta.h
   trunk/libgda/sqlite/gda-sqlite-provider.c
   trunk/libgda/sqlite/utils.c
   trunk/po/POTFILES.in
   trunk/po/POTFILES.skip
   trunk/providers/postgres/gda-postgres-ddl.c
   trunk/providers/postgres/gda-postgres-meta.c
   trunk/providers/postgres/gda-postgres-meta.h
   trunk/providers/postgres/gda-postgres-provider.c
   trunk/providers/skel-implementation/capi/   (props changed)
   trunk/providers/sqlite/sqlite_specs_create_table.xml.in
   trunk/tests/data-models/check_data_proxy.c
   trunk/tests/data-models/check_model_import.c
   trunk/tests/meta-store/common.c
   trunk/tests/providers/Makefile.am
   trunk/tests/providers/README
   trunk/tests/providers/TYPES_SCHEMA_SQLite.xml
   trunk/tests/providers/check_bdb.c
   trunk/tests/providers/check_mdb.c
   trunk/tests/providers/check_mysql.c
   trunk/tests/providers/check_oracle.c
   trunk/tests/providers/check_postgres.c
   trunk/tests/providers/check_sqlite.c
   trunk/tests/providers/prov-test-common.c
   trunk/tests/providers/prov-test-common.h
   trunk/tests/providers/prov-test-util.c
   trunk/tests/providers/prov-test-util.h
   trunk/tools/command-exec.c
   trunk/tools/gda-sql.c

Modified: trunk/doc/C/information_schema.png
==============================================================================
Binary files. No diff available.

Modified: trunk/doc/C/information_schema.svg
==============================================================================
--- trunk/doc/C/information_schema.svg	(original)
+++ trunk/doc/C/information_schema.svg	Wed Mar 12 21:18:24 2008
@@ -3,363 +3,358 @@
  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"; [
  <!ATTLIST svg xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink";>
 ]>
-<!-- Generated by Graphviz version 2.12 (Mon Apr 23 09:57:53 UTC 2007)
-     For user: (vmalerba) MALERBA Vivien DSNA&#45;DTI SIM ATM M204 p5713 -->
+<!-- Generated by Graphviz version 2.12 (Tue Sep  4 16:56:48 UTC 2007)
+     For user: (vivien) Vivien,,, -->
 <!-- Title: G Pages: 1 -->
-<svg width="17.14in" height="7.60in"
+<svg width="17.22in" height="7.82in"
  xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink";>
-<g id="graph0" class="graph" transform="scale(1.33333 1.33333) rotate(0) translate(4 544)">
+<g id="graph0" class="graph" transform="scale(1.33333 1.33333) rotate(0) translate(4 560)">
 <title>G</title>
-<polygon style="fill:white;stroke:white;" points="-4,4 -4,-544 1230,-544 1230,4 -4,4"/>
+<polygon style="fill:white;stroke:white;" points="-4,4 -4,-560 1236,-560 1236,4 -4,4"/>
 <!-- _attributes -->
 <g id="node1" class="node"><title>_attributes</title>
-<polygon style="fill:none;stroke:black;" points="210,-36 136,-36 136,-1.42109e-14 210,-0 210,-36"/>
-<text text-anchor="middle" x="173" y="-13" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_attributes</text>
+<polygon style="fill:none;stroke:black;" points="204,-38 130,-38 130,-2 204,-2 204,-38"/>
+<text text-anchor="middle" x="167" y="-16" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_attributes</text>
 </g>
 <!-- _information_schema_catalog_name -->
 <g id="node2" class="node"><title>_information_schema_catalog_name</title>
-<polygon style="fill:none;stroke:black;" points="685,-540 463,-540 463,-504 685,-504 685,-540"/>
-<text text-anchor="middle" x="574" y="-517" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_information_schema_catalog_name</text>
+<polygon style="fill:none;stroke:black;" points="721,-556 499,-556 499,-520 721,-520 721,-556"/>
+<text text-anchor="middle" x="610" y="-534" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_information_schema_catalog_name</text>
 </g>
 <!-- _builtin_data_types -->
 <g id="node3" class="node"><title>_builtin_data_types</title>
-<polygon style="fill:none;stroke:black;" points="918,-324 792,-324 792,-288 918,-288 918,-324"/>
-<text text-anchor="middle" x="855" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_builtin_data_types</text>
+<polygon style="fill:none;stroke:black;" points="924,-340 798,-340 798,-304 924,-304 924,-340"/>
+<text text-anchor="middle" x="861" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_builtin_data_types</text>
 </g>
 <!-- _udt -->
 <g id="node4" class="node"><title>_udt</title>
-<polygon style="fill:none;stroke:black;" points="990,-324 936,-324 936,-288 990,-288 990,-324"/>
-<text text-anchor="middle" x="963" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_udt</text>
+<polygon style="fill:none;stroke:black;" points="996,-340 942,-340 942,-304 996,-304 996,-340"/>
+<text text-anchor="middle" x="969" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_udt</text>
 </g>
 <!-- _element_types -->
 <g id="node5" class="node"><title>_element_types</title>
-<polygon style="fill:none;stroke:black;" points="508,-36 406,-36 406,-1.42109e-14 508,-0 508,-36"/>
-<text text-anchor="middle" x="457" y="-13" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_element_types</text>
+<polygon style="fill:none;stroke:black;" points="504,-38 402,-38 402,-2 504,-2 504,-38"/>
+<text text-anchor="middle" x="453" y="-16" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_element_types</text>
 </g>
 <!-- _schemata -->
 <g id="node6" class="node"><title>_schemata</title>
-<polygon style="fill:none;stroke:black;" points="611,-468 537,-468 537,-432 611,-432 611,-468"/>
-<text text-anchor="middle" x="574" y="-445" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_schemata</text>
+<polygon style="fill:none;stroke:black;" points="647,-484 573,-484 573,-448 647,-448 647,-484"/>
+<text text-anchor="middle" x="610" y="-462" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_schemata</text>
 </g>
 <!-- _schemata&#45;&gt;_information_schema_catalog_name -->
 <g id="edge2" class="edge"><title>_schemata&#45;&gt;_information_schema_catalog_name</title>
-<path style="fill:none;stroke:black;" d="M574,-468C574,-476 574,-485 574,-494"/>
-<polygon style="fill:black;stroke:black;" points="570.5,-494 574,-504 577.5,-494 570.5,-494"/>
+<path style="fill:none;stroke:black;" d="M610,-484C610,-492 610,-501 610,-510"/>
+<polygon style="fill:black;stroke:black;" points="606.5,-510 610,-520 613.5,-510 606.5,-510"/>
 </g>
 <!-- _udt_columns -->
 <g id="node8" class="node"><title>_udt_columns</title>
-<polygon style="fill:none;stroke:black;" points="1104,-252 1010,-252 1010,-216 1104,-216 1104,-252"/>
-<text text-anchor="middle" x="1057" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_udt_columns</text>
+<polygon style="fill:none;stroke:black;" points="1110,-266 1016,-266 1016,-230 1110,-230 1110,-266"/>
+<text text-anchor="middle" x="1063" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_udt_columns</text>
 </g>
 <!-- _udt_columns&#45;&gt;_udt -->
 <g id="edge4" class="edge"><title>_udt_columns&#45;&gt;_udt</title>
-<path style="fill:none;stroke:black;" d="M1033,-252C1022,-261 1007,-272 994,-282"/>
-<polygon style="fill:black;stroke:black;" points="991.9,-279.2 986,-288 996.1,-284.8 991.9,-279.2"/>
+<path style="fill:none;stroke:black;" d="M1040,-266C1028,-276 1013,-287 1000,-298"/>
+<polygon style="fill:black;stroke:black;" points="997.9,-295.2 992,-304 1002.1,-300.8 997.9,-295.2"/>
 </g>
 <!-- _enums -->
 <g id="node10" class="node"><title>_enums</title>
-<polygon style="fill:none;stroke:black;" points="992,-252 934,-252 934,-216 992,-216 992,-252"/>
-<text text-anchor="middle" x="963" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_enums</text>
+<polygon style="fill:none;stroke:black;" points="998,-266 940,-266 940,-230 998,-230 998,-266"/>
+<text text-anchor="middle" x="969" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_enums</text>
 </g>
 <!-- _enums&#45;&gt;_udt -->
 <g id="edge6" class="edge"><title>_enums&#45;&gt;_udt</title>
-<path style="fill:none;stroke:black;" d="M963,-252C963,-260 963,-269 963,-278"/>
-<polygon style="fill:black;stroke:black;" points="959.5,-278 963,-288 966.5,-278 959.5,-278"/>
+<path style="fill:none;stroke:black;" d="M969,-266C969,-275 969,-284 969,-294"/>
+<polygon style="fill:black;stroke:black;" points="965.5,-294 969,-304 972.5,-294 965.5,-294"/>
 </g>
 <!-- _domains -->
 <g id="node12" class="node"><title>_domains</title>
-<polygon style="fill:none;stroke:black;" points="760,-324 690,-324 690,-288 760,-288 760,-324"/>
-<text text-anchor="middle" x="725" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_domains</text>
+<polygon style="fill:none;stroke:black;" points="765,-340 695,-340 695,-304 765,-304 765,-340"/>
+<text text-anchor="middle" x="730" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_domains</text>
 </g>
 <!-- _domains&#45;&gt;_schemata -->
 <g id="edge8" class="edge"><title>_domains&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M717,-324C708,-344 691,-375 668,-396 654,-409 637,-421 620,-429"/>
-<polygon style="fill:black;stroke:black;" points="618.042,-426.084 611,-434 621.441,-432.203 618.042,-426.084"/>
+<path style="fill:none;stroke:black;" d="M721,-340C710,-359 693,-390 673,-412 664,-422 653,-433 643,-441"/>
+<polygon style="fill:black;stroke:black;" points="640.221,-438.781 635,-448 644.831,-444.049 640.221,-438.781"/>
 </g>
 <!-- _tables -->
 <g id="node14" class="node"><title>_tables</title>
-<polygon style="fill:none;stroke:black;" points="567,-324 513,-324 513,-288 567,-288 567,-324"/>
-<text text-anchor="middle" x="540" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_tables</text>
+<polygon style="fill:none;stroke:black;" points="582,-340 528,-340 528,-304 582,-304 582,-340"/>
+<text text-anchor="middle" x="555" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_tables</text>
 </g>
 <!-- _tables&#45;&gt;_schemata -->
 <g id="edge10" class="edge"><title>_tables&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M544,-324C549,-349 560,-393 568,-422"/>
-<polygon style="fill:black;stroke:black;" points="564.607,-422.881 570,-432 571.471,-421.508 564.607,-422.881"/>
+<path style="fill:none;stroke:black;" d="M562,-340C572,-365 589,-409 600,-438"/>
+<polygon style="fill:black;stroke:black;" points="596.774,-439.427 603,-448 603.479,-437.416 596.774,-439.427"/>
 </g>
 <!-- _collations -->
 <g id="node16" class="node"><title>_collations</title>
-<polygon style="fill:none;stroke:black;" points="523,-396 447,-396 447,-360 523,-360 523,-396"/>
-<text text-anchor="middle" x="485" y="-373" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_collations</text>
+<polygon style="fill:none;stroke:black;" points="498,-412 422,-412 422,-376 498,-376 498,-412"/>
+<text text-anchor="middle" x="460" y="-390" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_collations</text>
 </g>
 <!-- _collations&#45;&gt;_schemata -->
 <g id="edge12" class="edge"><title>_collations&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M507,-396C518,-405 532,-416 544,-426"/>
-<polygon style="fill:black;stroke:black;" points="541.9,-428.8 552,-432 546.1,-423.2 541.9,-428.8"/>
+<path style="fill:none;stroke:black;" d="M498,-412C518,-422 543,-433 564,-444"/>
+<polygon style="fill:black;stroke:black;" points="562.44,-447.137 573,-448 565.283,-440.74 562.44,-447.137"/>
 </g>
 <!-- _routines -->
 <g id="node18" class="node"><title>_routines</title>
-<polygon style="fill:none;stroke:black;" points="1100,-396 1032,-396 1032,-360 1100,-360 1100,-396"/>
-<text text-anchor="middle" x="1066" y="-373" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_routines</text>
+<polygon style="fill:none;stroke:black;" points="1090,-412 1022,-412 1022,-376 1090,-376 1090,-412"/>
+<text text-anchor="middle" x="1056" y="-390" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_routines</text>
 </g>
 <!-- _routines&#45;&gt;_schemata -->
 <g id="edge14" class="edge"><title>_routines&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M1032,-383C946,-396 720,-429 621,-443"/>
-<polygon style="fill:black;stroke:black;" points="620.119,-439.607 611,-445 621.492,-446.471 620.119,-439.607"/>
+<path style="fill:none;stroke:black;" d="M1022,-400C942,-413 747,-444 657,-458"/>
+<polygon style="fill:black;stroke:black;" points="656.119,-454.607 647,-460 657.492,-461.471 656.119,-454.607"/>
 </g>
 <!-- _views -->
 <g id="node20" class="node"><title>_views</title>
-<polygon style="fill:none;stroke:black;" points="544,-252 490,-252 490,-216 544,-216 544,-252"/>
-<text text-anchor="middle" x="517" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_views</text>
+<polygon style="fill:none;stroke:black;" points="548,-266 494,-266 494,-230 548,-230 548,-266"/>
+<text text-anchor="middle" x="521" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_views</text>
 </g>
 <!-- _views&#45;&gt;_tables -->
 <g id="edge16" class="edge"><title>_views&#45;&gt;_tables</title>
-<path style="fill:none;stroke:black;" d="M523,-252C526,-260 529,-269 531,-278"/>
-<polygon style="fill:black;stroke:black;" points="527.774,-279.427 534,-288 534.479,-277.416 527.774,-279.427"/>
+<path style="fill:none;stroke:black;" d="M529,-266C533,-275 538,-285 542,-295"/>
+<polygon style="fill:black;stroke:black;" points="538.74,-296.283 546,-304 545.137,-293.44 538.74,-296.283"/>
 </g>
 <!-- _character_sets -->
 <g id="node22" class="node"><title>_character_sets</title>
-<polygon style="fill:none;stroke:black;" points="457,-324 357,-324 357,-288 457,-288 457,-324"/>
-<text text-anchor="middle" x="407" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_character_sets</text>
+<polygon style="fill:none;stroke:black;" points="510,-340 410,-340 410,-304 510,-304 510,-340"/>
+<text text-anchor="middle" x="460" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_character_sets</text>
 </g>
 <!-- _character_sets&#45;&gt;_schemata -->
 <g id="edge18" class="edge"><title>_character_sets&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M409,-324C412,-344 419,-377 438,-396 461,-421 498,-435 527,-442"/>
-<polygon style="fill:black;stroke:black;" points="526.508,-445.471 537,-444 527.881,-438.607 526.508,-445.471"/>
+<path style="fill:none;stroke:black;" d="M479,-340C506,-366 554,-412 584,-441"/>
+<polygon style="fill:black;stroke:black;" points="581.454,-443.404 591,-448 586.404,-438.454 581.454,-443.404"/>
 </g>
 <!-- _character_sets&#45;&gt;_collations -->
 <g id="edge20" class="edge"><title>_character_sets&#45;&gt;_collations</title>
-<path style="fill:none;stroke:black;" d="M427,-324C437,-333 448,-343 458,-353"/>
-<polygon style="fill:black;stroke:black;" points="456.169,-356.049 466,-360 460.779,-350.781 456.169,-356.049"/>
+<path style="fill:none;stroke:black;" d="M460,-340C460,-348 460,-357 460,-366"/>
+<polygon style="fill:black;stroke:black;" points="456.5,-366 460,-376 463.5,-366 456.5,-366"/>
 </g>
 <!-- _triggers -->
 <g id="node25" class="node"><title>_triggers</title>
-<polygon style="fill:none;stroke:black;" points="628,-252 562,-252 562,-216 628,-216 628,-252"/>
-<text text-anchor="middle" x="595" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_triggers</text>
+<polygon style="fill:none;stroke:black;" points="632,-266 566,-266 566,-230 632,-230 632,-266"/>
+<text text-anchor="middle" x="599" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_triggers</text>
 </g>
 <!-- _triggers&#45;&gt;_schemata -->
 <g id="edge22" class="edge"><title>_triggers&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M593,-252C589,-290 581,-377 577,-422"/>
-<polygon style="fill:black;stroke:black;" points="573.512,-421.701 576,-432 580.478,-422.398 573.512,-421.701"/>
+<path style="fill:none;stroke:black;" d="M600,-266C602,-305 606,-393 609,-438"/>
+<polygon style="fill:black;stroke:black;" points="605.5,-438 609,-448 612.5,-438 605.5,-438"/>
 </g>
 <!-- _triggers&#45;&gt;_tables -->
 <g id="edge24" class="edge"><title>_triggers&#45;&gt;_tables</title>
-<path style="fill:none;stroke:black;" d="M581,-252C575,-260 567,-271 560,-280"/>
-<polygon style="fill:black;stroke:black;" points="557.2,-277.9 554,-288 562.8,-282.1 557.2,-277.9"/>
+<path style="fill:none;stroke:black;" d="M588,-266C583,-275 576,-285 571,-295"/>
+<polygon style="fill:black;stroke:black;" points="567.797,-293.559 566,-304 573.916,-296.958 567.797,-293.559"/>
 </g>
 <!-- _table_constraints -->
 <g id="node28" class="node"><title>_table_constraints</title>
-<polygon style="fill:none;stroke:black;" points="384,-252 268,-252 268,-216 384,-216 384,-252"/>
-<text text-anchor="middle" x="326" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_table_constraints</text>
-</g>
-<!-- _table_constraints&#45;&gt;_schemata -->
-<g id="edge28" class="edge"><title>_table_constraints&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M328,-252C330,-271 336,-301 348,-324 369,-363 379,-373 415,-396 449,-419 494,-432 527,-441"/>
-<polygon style="fill:black;stroke:black;" points="526.508,-444.471 537,-443 527.881,-437.607 526.508,-444.471"/>
+<polygon style="fill:none;stroke:black;" points="331,-266 215,-266 215,-230 331,-230 331,-266"/>
+<text text-anchor="middle" x="273" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_table_constraints</text>
 </g>
 <!-- _table_constraints&#45;&gt;_tables -->
 <g id="edge26" class="edge"><title>_table_constraints&#45;&gt;_tables</title>
-<path style="fill:none;stroke:black;" d="M380,-252C418,-265 469,-282 503,-294"/>
-<polygon style="fill:black;stroke:black;" points="502.416,-297.479 513,-297 504.427,-290.774 502.416,-297.479"/>
+<path style="fill:none;stroke:black;" d="M331,-257C380,-266 450,-281 518,-305"/>
+<polygon style="fill:black;stroke:black;" points="517.416,-308.479 528,-308 519.427,-301.774 517.416,-308.479"/>
 </g>
 <!-- _domain_constraints -->
-<g id="node31" class="node"><title>_domain_constraints</title>
-<polygon style="fill:none;stroke:black;" points="778,-252 646,-252 646,-216 778,-216 778,-252"/>
-<text text-anchor="middle" x="712" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_domain_constraints</text>
+<g id="node30" class="node"><title>_domain_constraints</title>
+<polygon style="fill:none;stroke:black;" points="782,-266 650,-266 650,-230 782,-230 782,-266"/>
+<text text-anchor="middle" x="716" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_domain_constraints</text>
 </g>
 <!-- _domain_constraints&#45;&gt;_schemata -->
-<g id="edge32" class="edge"><title>_domain_constraints&#45;&gt;_schemata</title>
-<path style="fill:none;stroke:black;" d="M700,-252C676,-290 620,-379 591,-423"/>
-<polygon style="fill:black;stroke:black;" points="587.797,-421.559 586,-432 593.916,-424.958 587.797,-421.559"/>
+<g id="edge30" class="edge"><title>_domain_constraints&#45;&gt;_schemata</title>
+<path style="fill:none;stroke:black;" d="M706,-266C700,-277 693,-291 686,-304 663,-351 637,-406 622,-439"/>
+<polygon style="fill:black;stroke:black;" points="618.863,-437.44 618,-448 625.26,-440.283 618.863,-437.44"/>
 </g>
 <!-- _domain_constraints&#45;&gt;_domains -->
-<g id="edge30" class="edge"><title>_domain_constraints&#45;&gt;_domains</title>
-<path style="fill:none;stroke:black;" d="M715,-252C716,-260 718,-269 720,-278"/>
-<polygon style="fill:black;stroke:black;" points="716.607,-278.881 722,-288 723.471,-277.508 716.607,-278.881"/>
+<g id="edge28" class="edge"><title>_domain_constraints&#45;&gt;_domains</title>
+<path style="fill:none;stroke:black;" d="M719,-266C721,-275 723,-285 725,-294"/>
+<polygon style="fill:black;stroke:black;" points="721.607,-294.881 727,-304 728.471,-293.508 721.607,-294.881"/>
 </g>
 <!-- _parameters -->
-<g id="node34" class="node"><title>_parameters</title>
-<polygon style="fill:none;stroke:black;" points="1226,-324 1142,-324 1142,-288 1226,-288 1226,-324"/>
-<text text-anchor="middle" x="1184" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_parameters</text>
+<g id="node33" class="node"><title>_parameters</title>
+<polygon style="fill:none;stroke:black;" points="1098,-340 1014,-340 1014,-304 1098,-304 1098,-340"/>
+<text text-anchor="middle" x="1056" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_parameters</text>
 </g>
 <!-- _parameters&#45;&gt;_routines -->
-<g id="edge34" class="edge"><title>_parameters&#45;&gt;_routines</title>
-<path style="fill:none;stroke:black;" d="M1154,-324C1139,-333 1120,-345 1104,-355"/>
-<polygon style="fill:black;stroke:black;" points="1102.04,-352.084 1095,-360 1105.44,-358.203 1102.04,-352.084"/>
+<g id="edge32" class="edge"><title>_parameters&#45;&gt;_routines</title>
+<path style="fill:none;stroke:black;" d="M1056,-340C1056,-348 1056,-357 1056,-366"/>
+<polygon style="fill:black;stroke:black;" points="1052.5,-366 1056,-376 1059.5,-366 1052.5,-366"/>
 </g>
 <!-- _routine_columns -->
-<g id="node36" class="node"><title>_routine_columns</title>
-<polygon style="fill:none;stroke:black;" points="1124,-324 1008,-324 1008,-288 1124,-288 1124,-324"/>
-<text text-anchor="middle" x="1066" y="-301" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_routine_columns</text>
+<g id="node35" class="node"><title>_routine_columns</title>
+<polygon style="fill:none;stroke:black;" points="1232,-340 1116,-340 1116,-304 1232,-304 1232,-340"/>
+<text text-anchor="middle" x="1174" y="-318" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_routine_columns</text>
 </g>
 <!-- _routine_columns&#45;&gt;_routines -->
-<g id="edge36" class="edge"><title>_routine_columns&#45;&gt;_routines</title>
-<path style="fill:none;stroke:black;" d="M1066,-324C1066,-332 1066,-341 1066,-350"/>
-<polygon style="fill:black;stroke:black;" points="1062.5,-350 1066,-360 1069.5,-350 1062.5,-350"/>
+<g id="edge34" class="edge"><title>_routine_columns&#45;&gt;_routines</title>
+<path style="fill:none;stroke:black;" d="M1144,-340C1129,-349 1110,-361 1094,-371"/>
+<polygon style="fill:black;stroke:black;" points="1092.04,-368.084 1085,-376 1095.44,-374.203 1092.04,-368.084"/>
 </g>
 <!-- _all_types -->
-<g id="node38" class="node"><title>_all_types</title>
-<ellipse style="fill:none;stroke:black;" cx="875" cy="-234" rx="41.1755" ry="18"/>
-<text text-anchor="middle" x="875" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_all_types</text>
+<g id="node37" class="node"><title>_all_types</title>
+<ellipse style="fill:none;stroke:black;" cx="880" cy="-248" rx="41.8014" ry="19.799"/>
+<text text-anchor="middle" x="880" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_all_types</text>
 </g>
 <!-- _all_types&#45;&gt;_builtin_data_types -->
-<g id="edge38" class="edge"><title>_all_types&#45;&gt;_builtin_data_types</title>
-<path style="fill:none;stroke:black;" d="M870,-252C868,-260 865,-269 863,-278"/>
-<polygon style="fill:black;stroke:black;" points="859.521,-277.416 860,-288 866.226,-279.427 859.521,-277.416"/>
+<g id="edge36" class="edge"><title>_all_types&#45;&gt;_builtin_data_types</title>
+<path style="fill:none;stroke:black;" d="M875,-268C873,-276 870,-285 868,-294"/>
+<polygon style="fill:black;stroke:black;" points="864.529,-293.508 866,-304 871.393,-294.881 864.529,-293.508"/>
 </g>
 <!-- _all_types&#45;&gt;_udt -->
-<g id="edge40" class="edge"><title>_all_types&#45;&gt;_udt</title>
-<path style="fill:none;stroke:black;" d="M895,-250C906,-259 920,-271 933,-281"/>
-<polygon style="fill:black;stroke:black;" points="931.169,-284.049 941,-288 935.779,-278.781 931.169,-284.049"/>
+<g id="edge38" class="edge"><title>_all_types&#45;&gt;_udt</title>
+<path style="fill:none;stroke:black;" d="M901,-266C912,-275 927,-287 939,-297"/>
+<polygon style="fill:black;stroke:black;" points="937.169,-300.049 947,-304 941.779,-294.781 937.169,-300.049"/>
 </g>
 <!-- _all_types&#45;&gt;_domains -->
-<g id="edge42" class="edge"><title>_all_types&#45;&gt;_domains</title>
-<path style="fill:none;stroke:black;" d="M847,-247C826,-258 795,-272 769,-285"/>
-<polygon style="fill:black;stroke:black;" points="767.717,-281.74 760,-289 770.56,-288.137 767.717,-281.74"/>
+<g id="edge40" class="edge"><title>_all_types&#45;&gt;_domains</title>
+<path style="fill:none;stroke:black;" d="M851,-262C829,-273 799,-288 774,-300"/>
+<polygon style="fill:black;stroke:black;" points="772.042,-297.084 765,-305 775.441,-303.203 772.042,-297.084"/>
 </g>
 <!-- _columns -->
-<g id="node42" class="node"><title>_columns</title>
-<polygon style="fill:none;stroke:black;" points="472,-252 402,-252 402,-216 472,-216 472,-252"/>
-<text text-anchor="middle" x="437" y="-229" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_columns</text>
+<g id="node41" class="node"><title>_columns</title>
+<polygon style="fill:none;stroke:black;" points="476,-266 406,-266 406,-230 476,-230 476,-266"/>
+<text text-anchor="middle" x="441" y="-244" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_columns</text>
 </g>
 <!-- _columns&#45;&gt;_tables -->
-<g id="edge44" class="edge"><title>_columns&#45;&gt;_tables</title>
-<path style="fill:none;stroke:black;" d="M463,-252C476,-261 492,-272 506,-282"/>
-<polygon style="fill:black;stroke:black;" points="504.738,-285.365 515,-288 508.621,-279.541 504.738,-285.365"/>
+<g id="edge42" class="edge"><title>_columns&#45;&gt;_tables</title>
+<path style="fill:none;stroke:black;" d="M469,-266C484,-276 503,-288 519,-299"/>
+<polygon style="fill:black;stroke:black;" points="517.559,-302.203 528,-304 520.958,-296.084 517.559,-302.203"/>
 </g>
 <!-- _columns&#45;&gt;_collations -->
-<g id="edge48" class="edge"><title>_columns&#45;&gt;_collations</title>
-<path style="fill:none;stroke:black;" d="M448,-252C454,-262 462,-276 466,-288 474,-308 478,-332 481,-350"/>
-<polygon style="fill:black;stroke:black;" points="477.607,-350.881 483,-360 484.471,-349.508 477.607,-350.881"/>
+<g id="edge46" class="edge"><title>_columns&#45;&gt;_collations</title>
+<path style="fill:none;stroke:black;" d="M424,-266C415,-276 406,-290 401,-304 397,-320 395,-326 401,-340 406,-352 415,-362 424,-370"/>
+<polygon style="fill:black;stroke:black;" points="421.9,-372.8 432,-376 426.1,-367.2 421.9,-372.8"/>
 </g>
 <!-- _columns&#45;&gt;_character_sets -->
-<g id="edge46" class="edge"><title>_columns&#45;&gt;_character_sets</title>
-<path style="fill:none;stroke:black;" d="M429,-252C426,-260 422,-270 419,-278"/>
-<polygon style="fill:black;stroke:black;" points="415.464,-277.415 415,-288 421.964,-280.015 415.464,-277.415"/>
+<g id="edge44" class="edge"><title>_columns&#45;&gt;_character_sets</title>
+<path style="fill:none;stroke:black;" d="M446,-266C448,-275 450,-285 453,-294"/>
+<polygon style="fill:black;stroke:black;" points="449.607,-294.881 455,-304 456.471,-293.508 449.607,-294.881"/>
 </g>
 <!-- _referential_constraints -->
-<g id="node46" class="node"><title>_referential_constraints</title>
-<polygon style="fill:none;stroke:black;" points="148,-180 2.84217e-14,-180 0,-144 148,-144 148,-180"/>
-<text text-anchor="middle" x="74" y="-157" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_referential_constraints</text>
+<g id="node45" class="node"><title>_referential_constraints</title>
+<polygon style="fill:none;stroke:black;" points="148,-190 2.84217e-14,-190 0,-154 148,-154 148,-190"/>
+<text text-anchor="middle" x="74" y="-168" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_referential_constraints</text>
 </g>
 <!-- _referential_constraints&#45;&gt;_table_constraints -->
-<g id="edge50" class="edge"><title>_referential_constraints&#45;&gt;_table_constraints</title>
-<path style="fill:none;stroke:black;" d="M131,-180C169,-191 218,-205 258,-216"/>
-<polygon style="fill:black;stroke:black;" points="257.416,-219.479 268,-219 259.427,-212.774 257.416,-219.479"/>
+<g id="edge48" class="edge"><title>_referential_constraints&#45;&gt;_table_constraints</title>
+<path style="fill:none;stroke:black;" d="M115,-190C143,-201 179,-215 211,-227"/>
+<polygon style="fill:black;stroke:black;" points="209.406,-230.158 220,-230 211.62,-223.517 209.406,-230.158"/>
 </g>
 <!-- _referential_constraints&#45;&gt;_table_constraints -->
-<g id="edge52" class="edge"><title>_referential_constraints&#45;&gt;_table_constraints</title>
-<path style="fill:none;stroke:black;" d="M143,-180C180,-190 224,-203 259,-213"/>
-<polygon style="fill:black;stroke:black;" points="258.416,-216.479 269,-216 260.427,-209.774 258.416,-216.479"/>
+<g id="edge50" class="edge"><title>_referential_constraints&#45;&gt;_table_constraints</title>
+<path style="fill:none;stroke:black;" d="M127,-190C157,-201 193,-215 223,-226"/>
+<polygon style="fill:black;stroke:black;" points="221.44,-229.137 232,-230 224.283,-222.74 221.44,-229.137"/>
 </g>
 <!-- _check_constraints -->
-<g id="node49" class="node"><title>_check_constraints</title>
-<ellipse style="fill:none;stroke:black;" cx="540" cy="-162" rx="66.1777" ry="18"/>
-<text text-anchor="middle" x="540" y="-157" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_check_constraints</text>
+<g id="node48" class="node"><title>_check_constraints</title>
+<ellipse style="fill:none;stroke:black;" cx="695" cy="-172" rx="66.799" ry="19.799"/>
+<text text-anchor="middle" x="695" y="-168" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_check_constraints</text>
 </g>
 <!-- _check_constraints&#45;&gt;_table_constraints -->
-<g id="edge54" class="edge"><title>_check_constraints&#45;&gt;_table_constraints</title>
-<path style="fill:none;stroke:black;" d="M498,-176C467,-186 425,-201 390,-213"/>
-<polygon style="fill:black;stroke:black;" points="388.573,-209.774 380,-216 390.584,-216.479 388.573,-209.774"/>
+<g id="edge52" class="edge"><title>_check_constraints&#45;&gt;_table_constraints</title>
+<path style="fill:none;stroke:black;" d="M646,-186C637,-188 628,-190 619,-192 616,-193 441,-221 341,-237"/>
+<polygon style="fill:black;stroke:black;" points="340.119,-233.607 331,-239 341.492,-240.471 340.119,-233.607"/>
 </g>
 <!-- _check_constraints&#45;&gt;_domain_constraints -->
-<g id="edge56" class="edge"><title>_check_constraints&#45;&gt;_domain_constraints</title>
-<path style="fill:none;stroke:black;" d="M576,-177C600,-187 632,-201 660,-212"/>
-<polygon style="fill:black;stroke:black;" points="658.44,-215.137 669,-216 661.283,-208.74 658.44,-215.137"/>
+<g id="edge54" class="edge"><title>_check_constraints&#45;&gt;_domain_constraints</title>
+<path style="fill:none;stroke:black;" d="M701,-192C703,-201 706,-211 708,-220"/>
+<polygon style="fill:black;stroke:black;" points="704.774,-221.427 711,-230 711.479,-219.416 704.774,-221.427"/>
 </g>
 <!-- _key_column_usage -->
-<g id="node52" class="node"><title>_key_column_usage</title>
-<polygon style="fill:none;stroke:black;" points="296,-180 166,-180 166,-144 296,-144 296,-180"/>
-<text text-anchor="middle" x="231" y="-157" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_key_column_usage</text>
+<g id="node51" class="node"><title>_key_column_usage</title>
+<polygon style="fill:none;stroke:black;" points="456,-190 326,-190 326,-154 456,-154 456,-190"/>
+<text text-anchor="middle" x="391" y="-168" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_key_column_usage</text>
 </g>
 <!-- _key_column_usage&#45;&gt;_table_constraints -->
-<g id="edge58" class="edge"><title>_key_column_usage&#45;&gt;_table_constraints</title>
-<path style="fill:none;stroke:black;" d="M255,-180C266,-189 281,-200 294,-210"/>
-<polygon style="fill:black;stroke:black;" points="291.9,-212.8 302,-216 296.1,-207.2 291.9,-212.8"/>
+<g id="edge56" class="edge"><title>_key_column_usage&#45;&gt;_table_constraints</title>
+<path style="fill:none;stroke:black;" d="M363,-190C347,-200 326,-213 309,-224"/>
+<polygon style="fill:black;stroke:black;" points="306.9,-221.2 301,-230 311.1,-226.8 306.9,-221.2"/>
 </g>
 <!-- _key_column_usage&#45;&gt;_columns -->
-<g id="edge60" class="edge"><title>_key_column_usage&#45;&gt;_columns</title>
-<path style="fill:none;stroke:black;" d="M288,-180C317,-189 352,-201 393,-216"/>
-<polygon style="fill:black;stroke:black;" points="391.406,-219.158 402,-219 393.62,-212.517 391.406,-219.158"/>
+<g id="edge58" class="edge"><title>_key_column_usage&#45;&gt;_columns</title>
+<path style="fill:none;stroke:black;" d="M403,-190C409,-199 417,-211 424,-222"/>
+<polygon style="fill:black;stroke:black;" points="420.732,-223.375 429,-230 426.668,-219.665 420.732,-223.375"/>
 </g>
 <!-- _check_column_usage -->
-<g id="node55" class="node"><title>_check_column_usage</title>
-<polygon style="fill:none;stroke:black;" points="456,-180 314,-180 314,-144 456,-144 456,-180"/>
-<text text-anchor="middle" x="385" y="-157" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_check_column_usage</text>
+<g id="node54" class="node"><title>_check_column_usage</title>
+<polygon style="fill:none;stroke:black;" points="308,-190 166,-190 166,-154 308,-154 308,-190"/>
+<text text-anchor="middle" x="237" y="-168" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_check_column_usage</text>
 </g>
 <!-- _check_column_usage&#45;&gt;_table_constraints -->
-<g id="edge62" class="edge"><title>_check_column_usage&#45;&gt;_table_constraints</title>
-<path style="fill:none;stroke:black;" d="M370,-180C363,-189 355,-199 347,-208"/>
-<polygon style="fill:black;stroke:black;" points="344.2,-205.9 341,-216 349.8,-210.1 344.2,-205.9"/>
+<g id="edge60" class="edge"><title>_check_column_usage&#45;&gt;_table_constraints</title>
+<path style="fill:none;stroke:black;" d="M246,-190C250,-199 255,-211 261,-221"/>
+<polygon style="fill:black;stroke:black;" points="257.74,-222.283 265,-230 264.137,-219.44 257.74,-222.283"/>
 </g>
 <!-- _check_column_usage&#45;&gt;_columns -->
-<g id="edge64" class="edge"><title>_check_column_usage&#45;&gt;_columns</title>
-<path style="fill:none;stroke:black;" d="M398,-180C404,-188 411,-199 418,-208"/>
-<polygon style="fill:black;stroke:black;" points="415.2,-210.1 424,-216 420.8,-205.9 415.2,-210.1"/>
+<g id="edge62" class="edge"><title>_check_column_usage&#45;&gt;_columns</title>
+<path style="fill:none;stroke:black;" d="M285,-190C319,-202 364,-218 396,-231"/>
+<polygon style="fill:black;stroke:black;" points="395.415,-234.536 406,-235 398.015,-228.036 395.415,-234.536"/>
 </g>
 <!-- _view_column_usage -->
-<g id="node58" class="node"><title>_view_column_usage</title>
-<polygon style="fill:none;stroke:black;" points="760,-180 624,-180 624,-144 760,-144 760,-180"/>
-<text text-anchor="middle" x="692" y="-157" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_view_column_usage</text>
+<g id="node57" class="node"><title>_view_column_usage</title>
+<polygon style="fill:none;stroke:black;" points="610,-190 474,-190 474,-154 610,-154 610,-190"/>
+<text text-anchor="middle" x="542" y="-168" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_view_column_usage</text>
 </g>
 <!-- _view_column_usage&#45;&gt;_views -->
-<g id="edge66" class="edge"><title>_view_column_usage&#45;&gt;_views</title>
-<path style="fill:none;stroke:black;" d="M643,-180C618,-189 588,-201 553,-216"/>
-<polygon style="fill:black;stroke:black;" points="551.717,-212.74 544,-220 554.56,-219.137 551.717,-212.74"/>
+<g id="edge64" class="edge"><title>_view_column_usage&#45;&gt;_views</title>
+<path style="fill:none;stroke:black;" d="M537,-190C535,-199 531,-210 529,-220"/>
+<polygon style="fill:black;stroke:black;" points="525.521,-219.416 526,-230 532.226,-221.427 525.521,-219.416"/>
 </g>
 <!-- _view_column_usage&#45;&gt;_columns -->
-<g id="edge68" class="edge"><title>_view_column_usage&#45;&gt;_columns</title>
-<path style="fill:none;stroke:black;" d="M624,-178C577,-190 518,-204 482,-216"/>
-<polygon style="fill:black;stroke:black;" points="480.573,-212.774 472,-219 482.584,-219.479 480.573,-212.774"/>
+<g id="edge66" class="edge"><title>_view_column_usage&#45;&gt;_columns</title>
+<path style="fill:none;stroke:black;" d="M518,-190C505,-200 488,-213 473,-224"/>
+<polygon style="fill:black;stroke:black;" points="470.9,-221.2 465,-230 475.1,-226.8 470.9,-221.2"/>
 </g>
 <!-- _domain_column_usage -->
-<g id="node61" class="node"><title>_domain_column_usage</title>
-<ellipse style="fill:none;stroke:black;" cx="859" cy="-162" rx="81.1777" ry="18"/>
-<text text-anchor="middle" x="859" y="-157" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_domain_column_usage</text>
+<g id="node60" class="node"><title>_domain_column_usage</title>
+<ellipse style="fill:none;stroke:black;" cx="862" cy="-172" rx="81.799" ry="19.799"/>
+<text text-anchor="middle" x="862" y="-168" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_domain_column_usage</text>
 </g>
 <!-- _domain_column_usage&#45;&gt;_domains -->
-<g id="edge70" class="edge"><title>_domain_column_usage&#45;&gt;_domains</title>
-<path style="fill:none;stroke:black;" d="M846,-180C832,-199 809,-229 787,-252 778,-262 766,-273 756,-281"/>
-<polygon style="fill:black;stroke:black;" points="753.221,-278.781 748,-288 757.831,-284.049 753.221,-278.781"/>
+<g id="edge68" class="edge"><title>_domain_column_usage&#45;&gt;_domains</title>
+<path style="fill:none;stroke:black;" d="M849,-192C835,-212 813,-244 791,-268 782,-278 771,-289 761,-297"/>
+<polygon style="fill:black;stroke:black;" points="758.221,-294.781 753,-304 762.831,-300.049 758.221,-294.781"/>
 </g>
 <!-- _domain_column_usage&#45;&gt;_columns -->
-<g id="edge72" class="edge"><title>_domain_column_usage&#45;&gt;_columns</title>
-<path style="fill:none;stroke:black;" d="M800,-175C790,-177 779,-178 769,-180 645,-200 608,-185 482,-216"/>
-<polygon style="fill:black;stroke:black;" points="480.573,-212.774 472,-219 482.584,-219.479 480.573,-212.774"/>
+<g id="edge70" class="edge"><title>_domain_column_usage&#45;&gt;_columns</title>
+<path style="fill:none;stroke:black;" d="M803,-186C792,-188 781,-190 771,-192 648,-213 611,-195 486,-228"/>
+<polygon style="fill:black;stroke:black;" points="484.573,-224.774 476,-231 486.584,-231.479 484.573,-224.774"/>
 </g>
 <!-- _constraint_column_usage -->
-<g id="node64" class="node"><title>_constraint_column_usage</title>
-<ellipse style="fill:none;stroke:black;" cx="308" cy="-90" rx="87.1767" ry="18"/>
-<text text-anchor="middle" x="308" y="-85" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_constraint_column_usage</text>
+<g id="node63" class="node"><title>_constraint_column_usage</title>
+<ellipse style="fill:none;stroke:black;" cx="303" cy="-96" rx="87.8001" ry="19.799"/>
+<text text-anchor="middle" x="303" y="-92" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_constraint_column_usage</text>
 </g>
 <!-- _constraint_column_usage&#45;&gt;_key_column_usage -->
-<g id="edge74" class="edge"><title>_constraint_column_usage&#45;&gt;_key_column_usage</title>
-<path style="fill:none;stroke:black;" d="M289,-108C279,-117 268,-127 258,-137"/>
-<polygon style="fill:black;stroke:black;" points="255.221,-134.781 250,-144 259.831,-140.049 255.221,-134.781"/>
+<g id="edge72" class="edge"><title>_constraint_column_usage&#45;&gt;_key_column_usage</title>
+<path style="fill:none;stroke:black;" d="M326,-116C337,-126 351,-137 362,-147"/>
+<polygon style="fill:black;stroke:black;" points="360.169,-150.049 370,-154 364.779,-144.781 360.169,-150.049"/>
 </g>
 <!-- _constraint_column_usage&#45;&gt;_check_column_usage -->
-<g id="edge76" class="edge"><title>_constraint_column_usage&#45;&gt;_check_column_usage</title>
-<path style="fill:none;stroke:black;" d="M327,-108C337,-117 348,-127 358,-137"/>
-<polygon style="fill:black;stroke:black;" points="356.169,-140.049 366,-144 360.779,-134.781 356.169,-140.049"/>
+<g id="edge74" class="edge"><title>_constraint_column_usage&#45;&gt;_check_column_usage</title>
+<path style="fill:none;stroke:black;" d="M286,-116C278,-125 268,-136 260,-146"/>
+<polygon style="fill:black;stroke:black;" points="256.951,-144.169 253,-154 262.219,-148.779 256.951,-144.169"/>
 </g>
 <!-- _view_table_usage -->
-<g id="node67" class="node"><title>_view_table_usage</title>
-<ellipse style="fill:none;stroke:black;" cx="692" cy="-90" rx="66.1777" ry="18"/>
-<text text-anchor="middle" x="692" y="-85" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_view_table_usage</text>
+<g id="node66" class="node"><title>_view_table_usage</title>
+<ellipse style="fill:none;stroke:black;" cx="542" cy="-96" rx="66.799" ry="19.799"/>
+<text text-anchor="middle" x="542" y="-92" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_view_table_usage</text>
 </g>
 <!-- _view_table_usage&#45;&gt;_view_column_usage -->
-<g id="edge78" class="edge"><title>_view_table_usage&#45;&gt;_view_column_usage</title>
-<path style="fill:none;stroke:black;" d="M692,-108C692,-116 692,-125 692,-134"/>
-<polygon style="fill:black;stroke:black;" points="688.5,-134 692,-144 695.5,-134 688.5,-134"/>
+<g id="edge76" class="edge"><title>_view_table_usage&#45;&gt;_view_column_usage</title>
+<path style="fill:none;stroke:black;" d="M542,-116C542,-125 542,-135 542,-144"/>
+<polygon style="fill:black;stroke:black;" points="538.5,-144 542,-154 545.5,-144 538.5,-144"/>
 </g>
 <!-- _constraint_table_usage -->
-<g id="node69" class="node"><title>_constraint_table_usage</title>
-<ellipse style="fill:none;stroke:black;" cx="308" cy="-18" rx="80.1777" ry="18"/>
-<text text-anchor="middle" x="308" y="-13" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_constraint_table_usage</text>
+<g id="node68" class="node"><title>_constraint_table_usage</title>
+<ellipse style="fill:none;stroke:black;" cx="303" cy="-20" rx="80.799" ry="19.799"/>
+<text text-anchor="middle" x="303" y="-16" style="font-family:Nimbus Roman No9 L;font-weight:regular;font-size:11.34pt;">_constraint_table_usage</text>
 </g>
 <!-- _constraint_table_usage&#45;&gt;_constraint_column_usage -->
-<g id="edge80" class="edge"><title>_constraint_table_usage&#45;&gt;_constraint_column_usage</title>
-<path style="fill:none;stroke:black;" d="M308,-36C308,-44 308,-53 308,-62"/>
-<polygon style="fill:black;stroke:black;" points="304.5,-62 308,-72 311.5,-62 304.5,-62"/>
+<g id="edge78" class="edge"><title>_constraint_table_usage&#45;&gt;_constraint_column_usage</title>
+<path style="fill:none;stroke:black;" d="M303,-40C303,-48 303,-57 303,-66"/>
+<polygon style="fill:black;stroke:black;" points="299.5,-66 303,-76 306.5,-66 299.5,-66"/>
 </g>
 </g>
 </svg>

Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt	(original)
+++ trunk/doc/C/libgda-4.0-sections.txt	Wed Mar 12 21:18:24 2008
@@ -1164,7 +1164,7 @@
 <TITLE>GdaBatch</TITLE>
 GdaBatch
 gda_batch_new
-gda_batch_copy
+gda_batch_new_copy
 gda_batch_add_statement
 gda_batch_remove_statement
 gda_batch_serialize
@@ -1364,9 +1364,13 @@
 gda_meta_store_new
 gda_meta_store_new_with_file
 gda_meta_store_get_version
-gda_meta_store_get_internal_connection
 gda_meta_store_extract
 gda_meta_store_modify
+gda_meta_store_schema_get_structure
+gda_meta_store_get_attribute_value
+gda_meta_store_set_attribute_value
+gda_meta_store_schema_add_custom_object
+gda_meta_store_get_internal_connection
 <SUBSECTION Standard>
 GDA_IS_META_STORE
 GDA_META_STORE
@@ -1380,8 +1384,8 @@
 <FILE>gda-meta-struct</FILE>
 <TITLE>GdaMetaStruct</TITLE>
 GdaMetaStruct
+GdaMetaStructFeature
 GdaMetaStructError
-GDA_META_STRUCT_ERROR
 GdaMetaDbObjectType
 GdaMetaDbObject
 GDA_META_DB_OBJECT
@@ -1393,12 +1397,15 @@
 GDA_META_TABLE_COLUMN
 GdaMetaTableForeignKey
 GDA_META_TABLE_FOREIGN_KEY
+GDA_META_STRUCT_ERROR
 gda_meta_struct_new
 gda_meta_struct_complement
 GdaMetaSortType
 gda_meta_struct_sort_db_objects
 gda_meta_struct_get_db_object
 gda_meta_struct_get_table_column
+GdaMetaGraphInfo
+gda_meta_struct_dump_as_graph
 </SECTION>
 
 <SECTION>

Modified: trunk/doc/C/libgda-4.0.types.in
==============================================================================
--- trunk/doc/C/libgda-4.0.types.in	(original)
+++ trunk/doc/C/libgda-4.0.types.in	Wed Mar 12 21:18:24 2008
@@ -58,3 +58,4 @@
 gda_holder_get_type
 gda_set_get_type
 gda_meta_store_get_type
+gda_meta_struct_get_type

Modified: trunk/doc/C/tmpl/gda-batch.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-batch.sgml	(original)
+++ trunk/doc/C/tmpl/gda-batch.sgml	Wed Mar 12 21:18:24 2008
@@ -43,6 +43,15 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION gda_batch_new_copy ##### -->
+<para>
+
+</para>
+
+ orig: 
+ Returns: 
+
+
 <!-- ##### FUNCTION gda_batch_add_statement ##### -->
 <para>
 

Modified: trunk/doc/C/tmpl/gda-meta-store.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-meta-store.sgml	(original)
+++ trunk/doc/C/tmpl/gda-meta-store.sgml	Wed Mar 12 21:18:24 2008
@@ -66,6 +66,7 @@
 
 @gdametastore: the object which received the signal.
 @arg1: 
+ Returns: 
 
 <!-- ##### ARG GdaMetaStore:cnc ##### -->
 <para>
@@ -87,6 +88,10 @@
 @GDA_META_STORE_INTERNAL_ERROR: 
 @GDA_META_STORE_MODIFY_CONTENTS_ERROR: 
 @GDA_META_STORE_EXTRACT_SQL_ERROR: 
+ GDA_META_STORE_ATTRIBUTE_NOT_FOUND_ERROR: 
+ GDA_META_STORE_ATTRIBUTE_ERROR: 
+ GDA_META_STORE_SCHEMA_OBJECT_CONFLICT_ERROR: 
+ GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR: 
 
 <!-- ##### STRUCT GdaMetaStoreChange ##### -->
 <para>
@@ -143,38 +148,83 @@
 @Returns: 
 
 
-<!-- ##### FUNCTION gda_meta_store_get_internal_connection ##### -->
+<!-- ##### FUNCTION gda_meta_store_extract ##### -->
 <para>
 
 </para>
 
 @store: 
+ select_sql: 
+ error: 
+ Varargs: 
 @Returns: 
 
 
-<!-- ##### FUNCTION gda_meta_store_extract ##### -->
+<!-- ##### FUNCTION gda_meta_store_modify ##### -->
 <para>
 
 </para>
 
 @store: 
- select_sql: 
+ table_name: 
+ new_data: 
+ condition: 
 @error: 
 @Varargs: 
 @Returns: 
 
 
-<!-- ##### FUNCTION gda_meta_store_modify ##### -->
+<!-- ##### FUNCTION gda_meta_store_schema_get_structure ##### -->
 <para>
 
 </para>
 
 @store: 
- table_name: 
- new_data: 
- condition: 
 @error: 
- Varargs: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_meta_store_get_attribute_value ##### -->
+<para>
+
+</para>
+
+ store: 
+ att_name: 
+ att_value: 
+ error: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_meta_store_set_attribute_value ##### -->
+<para>
+
+</para>
+
+ store: 
+ att_name: 
+ att_value: 
+ error: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_meta_store_schema_add_custom_object ##### -->
+<para>
+
+</para>
+
+ store: 
+ xml_description: 
+ error: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gda_meta_store_get_internal_connection ##### -->
+<para>
+
+</para>
+
+ store: 
 @Returns: 
 
 

Modified: trunk/doc/C/tmpl/gda-meta-struct.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-meta-struct.sgml	(original)
+++ trunk/doc/C/tmpl/gda-meta-struct.sgml	Wed Mar 12 21:18:24 2008
@@ -40,6 +40,40 @@
 }
 gda_meta_struct_free (mstruct);
   </programlisting>
+  If now the database object type is not known, one can use the following code:
+  <programlisting>
+GdaMetaStruct *mstruct;
+GdaMetaDbObject *dbo;
+GValue *catalog, *schema, *name;
+
+/* Define name (and optionnally catalog and schema) */
+[...]
+
+mstruct = gda_meta_struct_new ();
+gda_meta_struct_complement (mstruct, store, GDA_META_DB_UNKNOWN, catalog, schema, name, NULL);
+dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
+if (!dbo)
+        g_print ("Object not found\n");
+else {
+        if ((dbo->obj_type == GDA_META_DB_TABLE) || (dbo->obj_type == GDA_META_DB_VIEW)) {
+                if (dbo->obj_type == GDA_META_DB_TABLE)
+                        g_print ("Is a table\n");
+                else if (dbo->obj_type == GDA_META_DB_VIEW) {
+                        g_print ("Is a view, definition is:\n");
+                        g_print ("%s\n", GDA_META_DB_OBJECT_GET_VIEW (dbo)->view_def);
+                }
+
+                GSList *list;
+                for (list = GDA_META_DB_OBJECT_GET_TABLE (dbo)->columns; list; list = list->next) {
+                        GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
+                        g_print ("COLUMN: %s (%s)\n", tcol->column_name, tcol->column_type);
+                }
+        }
+        else 
+                g_print ("Not a table or a view\n");
+}
+gda_meta_struct_free (mstruct);
+  </programlisting>
 </para>
 
 <!-- ##### SECTION See_Also ##### -->
@@ -55,25 +89,30 @@
 
 </para>
 
- object: 
- db_objects: 
- priv: 
 
-<!-- ##### ENUM GdaMetaStructError ##### -->
+<!-- ##### ARG GdaMetaStruct:features ##### -->
 <para>
 
 </para>
 
- GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR: 
- GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR: 
- GDA_META_STRUCT_INCOHERENCE_ERROR: 
-
-<!-- ##### MACRO GDA_META_STRUCT_ERROR ##### -->
+<!-- ##### ENUM GdaMetaStructFeature ##### -->
 <para>
 
 </para>
 
+ GDA_META_STRUCT_FEATURE_NONE: 
+ GDA_META_STRUCT_FEATURE_FOREIGN_KEYS: 
+ GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES: 
+ GDA_META_STRUCT_FEATURE_ALL: 
 
+<!-- ##### ENUM GdaMetaStructError ##### -->
+<para>
+
+</para>
+
+ GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR: 
+ GDA_META_STRUCT_DUPLICATE_OBJECT_ERROR: 
+ GDA_META_STRUCT_INCOHERENCE_ERROR: 
 
 <!-- ##### ENUM GdaMetaDbObjectType ##### -->
 <para>
@@ -169,11 +208,19 @@
 @x: 
 
 
+<!-- ##### MACRO GDA_META_STRUCT_ERROR ##### -->
+<para>
+
+</para>
+
+
+
 <!-- ##### FUNCTION gda_meta_struct_new ##### -->
 <para>
 
 </para>
 
+ features: 
 @Returns: 
 
 
@@ -234,3 +281,21 @@
 @Returns: 
 
 
+<!-- ##### ENUM GdaMetaGraphInfo ##### -->
+<para>
+
+</para>
+
+ GDA_META_GRAPH_COLUMNS: 
+
+<!-- ##### FUNCTION gda_meta_struct_dump_as_graph ##### -->
+<para>
+
+</para>
+
+ mstruct: 
+ info: 
+ error: 
+ Returns: 
+
+

Modified: trunk/doc/C/tmpl/gda-server-provider.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-server-provider.sgml	(original)
+++ trunk/doc/C/tmpl/gda-server-provider.sgml	Wed Mar 12 21:18:24 2008
@@ -91,18 +91,18 @@
 for more information.
 </para>
 
- info: 
- btypes: 
+ _info: 
+ _btypes: 
+ _schemata: 
 @schemata: 
+ _tables_views: 
 @tables_views: 
- tables_views_s: 
+ _columns: 
 @columns: 
- columns_t: 
- columns_c: 
+ _constraints_tab: 
 @constraints_tab: 
- constraints_tab_s: 
+ _constraints_ref: 
 @constraints_ref: 
- constraints_ref_c: 
 
 <!-- ##### USER_FUNCTION GdaServerProviderAsyncCallback ##### -->
 <para>

Modified: trunk/libgda/gda-batch.c
==============================================================================
--- trunk/libgda/gda-batch.c	(original)
+++ trunk/libgda/gda-batch.c	Wed Mar 12 21:18:24 2008
@@ -150,7 +150,7 @@
 
 
 /**
- * gda_batch_copy
+ * gda_batch_new_copy
  * @orig: a #GdaBatch to make a copy of
  * 
  * Copy constructor
@@ -158,7 +158,7 @@
  * Returns: a the new copy of @orig
  */
 GdaBatch *
-gda_batch_copy (GdaBatch *orig)
+gda_batch_new_copy (GdaBatch *orig)
 {
 	GObject *obj;
 	GdaBatch *batch;

Modified: trunk/libgda/gda-config.c
==============================================================================
--- trunk/libgda/gda-config.c	(original)
+++ trunk/libgda/gda-config.c	Wed Mar 12 21:18:24 2008
@@ -724,7 +724,7 @@
 
 /**
  * gda_config_remove_dsn
- * @info: a pointer to a filled GdaDataSourceInfo structure
+ * @dsn_name: the name of the DSN to remove
  * @error: a place to store errors, or %NULL
  *
  * Add or update a DSN from the definition in @info

Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c	(original)
+++ trunk/libgda/gda-connection.c	Wed Mar 12 21:18:24 2008
@@ -1754,12 +1754,15 @@
 #ifdef GDA_DEBUG
 #define ASSERT_TABLE_NAME(x,y) g_assert (!strcmp ((x), (y)))
 #define WARN_METHOD_NOT_IMPLEMENTED(prov,method) g_warning ("Provider '%s' does not implement the META method '%s()', please report the error to bugzilla.gnome.org", gda_server_provider_get_name (prov), (method))
+#define WARN_META_UPDATE_FAILURE(x,method) if (!(x)) g_print ("%s (meta method => %s) ERROR: %s\n", __FUNCTION__, (method), error && *error && (*error)->message ? (*error)->message : "???")
 #else
 #define ASSERT_TABLE_NAME(x,y)
 #define WARN_METHOD_NOT_IMPLEMENTED(prov,method)
+#define WARN_META_UPDATE_FAILURE(x,method)
 #endif
 	const gchar *tname = context->table_name;
 	GdaMetaStore *store;
+	gboolean retval;
 
 	if (*tname != '_')
 		return TRUE;
@@ -1772,67 +1775,61 @@
 		 *  - none
 		 */
 		ASSERT_TABLE_NAME (tname, "builtin_data_types");
-		if (!PROV_CLASS (provider)->meta_funcs.btypes) {
-			WARN_METHOD_NOT_IMPLEMENTED (provider, "btypes");
+		if (!PROV_CLASS (provider)->meta_funcs._btypes) {
+			WARN_METHOD_NOT_IMPLEMENTED (provider, "_btypes");
 			break;
 		}
-		return PROV_CLASS (provider)->meta_funcs.btypes (provider, cnc, store, context, error);
+		retval = PROV_CLASS (provider)->meta_funcs._btypes (provider, cnc, store, context, error);
+		WARN_META_UPDATE_FAILURE (retval, "_btypes");
+		return retval;
 	}
 	case 'i':
 		/* _information_schema_catalog_name, params: 
 		 *  - none
 		 */
 		ASSERT_TABLE_NAME (tname, "information_schema_catalog_name");
-		if (!PROV_CLASS (provider)->meta_funcs.info) {
-			WARN_METHOD_NOT_IMPLEMENTED (provider, "info");
+		if (!PROV_CLASS (provider)->meta_funcs._info) {
+			WARN_METHOD_NOT_IMPLEMENTED (provider, "_info");
 			break;
 		}
-		return PROV_CLASS (provider)->meta_funcs.info (provider, cnc, store, context, error);
+		retval = PROV_CLASS (provider)->meta_funcs._info (provider, cnc, store, context, error);
+		WARN_META_UPDATE_FAILURE (retval, "_info");
+		return retval;
 	case 'c': 
 		if ((tname[1] == 'o') && (tname[2] == 'l') && (tname[3] == 'u')) {
 			/* _columns,  params: 
-			 *  - none
-			 *  - @table_schema AND @table_name
-			 *  - @table_schema AND @table_name AND @column_name
+			 *  -0- @table_catalog, @table_schema, @table_name
+			 *  -1- @character_set_catalog, @character_set_schema, @character_set_name
+			 *  -2- @collation_catalog, @collation_schema, @collation_name
 			 */
-			const GValue *p_table_schema = NULL;
-			const GValue *p_table_name = NULL;
-			const GValue *p_column_name = NULL;
-			
-			if (check_parameters (context, error, 3,
-					      &p_table_schema, G_TYPE_STRING,
-					      &p_table_name, G_TYPE_STRING,
-					      &p_column_name, G_TYPE_STRING, NULL,
-					      "table_schema", &p_table_schema, "table_name", &p_table_name, "column_name", &p_column_name, NULL,
-					      "table_schema", &p_table_schema, "table_name", &p_table_name, NULL,
-					      NULL) < 0)
+			const GValue *catalog = NULL;
+			const GValue *schema = NULL;
+			const GValue *name = NULL;
+			gint i;
+			i = check_parameters (context, error, 3,
+					      &catalog, G_TYPE_STRING,
+					      &schema, G_TYPE_STRING,
+					      &name, G_TYPE_STRING, NULL,
+					      "table_catalog", &catalog, "table_schema", &schema, "table_name", &name, NULL,
+					      "character_set_catalog", &catalog, "character_set_schema", &schema, "character_set_name", &name, NULL,
+					      "collation_catalog", &catalog, "collation_schema", &schema, "collation_name", &name, NULL);
+			if (i < 0)
 				return FALSE;
 			
 			ASSERT_TABLE_NAME (tname, "columns");
-			if (p_table_schema) {
-				if (p_column_name) {
-					if (!PROV_CLASS (provider)->meta_funcs.columns_c) {
-						WARN_METHOD_NOT_IMPLEMENTED (provider, "columns_c");
-						break;
-					}
-					return PROV_CLASS (provider)->meta_funcs.columns_c (provider, cnc, store, context, error, 
-											    p_table_schema, p_table_name, p_column_name);
-				}
-				else {
-					if (!PROV_CLASS (provider)->meta_funcs.columns_t) {
-						WARN_METHOD_NOT_IMPLEMENTED (provider, "columns_t");
-						break;
-					}
-					return PROV_CLASS (provider)->meta_funcs.columns_t (provider, cnc, store, context, error, 
-											    p_table_schema, p_table_name);
-				}
-			}
-			else {
+			if (i == 0) {
 				if (!PROV_CLASS (provider)->meta_funcs.columns) {
 					WARN_METHOD_NOT_IMPLEMENTED (provider, "columns");
 					break;
 				}
-				return PROV_CLASS (provider)->meta_funcs.columns (provider, cnc, store, context, error);
+				retval = PROV_CLASS (provider)->meta_funcs.columns (provider, cnc, store, context, error, 
+										    catalog, schema, name);
+				WARN_META_UPDATE_FAILURE (retval, "columns");
+				return retval;
+			}
+			else {
+				/* nothing to do */
+				return TRUE;
 			}
 		}
 		break;
@@ -1840,120 +1837,127 @@
 	case 'r': 
 		if ((tname[1] == 'e') && (tname[2] == 'f')) {
 			/* _referential_constraints, params: 
-			 *  - none
-			 *  - @constraint_schema AND @constraint_name
+			 *  -0- @table_catalog, @table_schema, @table_name, @constraint_name
+			 *  -0- @ref_table_catalog, @ref_table_schema, @ref_table_name, @ref_constraint_name
 			 */
-			const GValue *p_constraint_schema = NULL;
-			const GValue *p_constraint_name = NULL;
-			if (check_parameters (context, error, 3,
-					      &p_constraint_schema, G_TYPE_STRING,
-					      &p_constraint_name, G_TYPE_STRING, NULL,
-					      "constraint_schema", &p_constraint_schema, "constraint_name", &p_constraint_name, NULL,
-					      NULL) < 0)
+			const GValue *catalog = NULL;
+			const GValue *schema = NULL;
+			const GValue *tabname = NULL;
+			const GValue *cname = NULL;
+			gint i;
+			i = check_parameters (context, error, 2,
+					      &catalog, G_TYPE_STRING,
+					      &schema, G_TYPE_STRING,
+					      &tabname, G_TYPE_STRING,
+					      &cname, G_TYPE_STRING, NULL,
+					      "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "constraint_name", &cname, NULL,
+					      "ref_table_catalog", &catalog, "ref_table_schema", &schema, "ref_table_name", &tabname, "ref_constraint_name", &cname, NULL);
+			if (i < 0)
 				return FALSE;
 			
 			ASSERT_TABLE_NAME (tname, "referential_constraints");
-			if (p_constraint_schema) {
-				if (!PROV_CLASS (provider)->meta_funcs.constraints_ref_c) {
-					WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_ref_c");
-					break;
-				}
-				return PROV_CLASS (provider)->meta_funcs.constraints_ref_c (provider, cnc, store, context, error, 
-											    p_constraint_schema, p_constraint_name);
-			}
-			else {
+			if (i == 0) {
 				if (!PROV_CLASS (provider)->meta_funcs.constraints_ref) {
 					WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_ref");
 					break;
 				}
-				return PROV_CLASS (provider)->meta_funcs.constraints_ref (provider, cnc, store, context, error);
+				retval = PROV_CLASS (provider)->meta_funcs.constraints_ref (provider, cnc, store, context, error, 
+											    catalog, schema, tabname, cname);
+				WARN_META_UPDATE_FAILURE (retval, "constraints_ref");
+				return retval;
+			}
+			else {
+				/* nothing to do */
+				return TRUE;
 			}
 		}
 		break;
 
 	case 's': {
-		/* _schemata, params: 
-		 *  - none
-		 *  - @schema_name
+		/* _schemata, params:
+		 *  -0- @catalog_name, @schema_name 
+		 *  -1- @catalog_name
 		 */
-		GValue *p_schema_name = NULL;
-		if (check_parameters (context, error, 2,
-				      &p_schema_name, G_TYPE_STRING, NULL,
-				      "schema_name", &p_schema_name, NULL,
-				      NULL) < 0)
+		GValue *catalog = NULL;
+		GValue *schema = NULL;
+		gint i;
+		i = check_parameters (context, error, 2,
+				      &schema, G_TYPE_STRING, NULL,
+				      "catalog_name", &catalog, "schema_name", &schema, NULL,
+				      "catalog_name", &catalog, NULL);
+		if (i < 0)
 			return FALSE;
 		ASSERT_TABLE_NAME (tname, "schemata");
+
 		if (!PROV_CLASS (provider)->meta_funcs.schemata) {
 			WARN_METHOD_NOT_IMPLEMENTED (provider, "schemata");
 			break;
 		}
-		return PROV_CLASS (provider)->meta_funcs.schemata (provider, cnc, store, context, error, p_schema_name);
+		retval = PROV_CLASS (provider)->meta_funcs.schemata (provider, cnc, store, context, error, 
+								     catalog, schema);
+		WARN_META_UPDATE_FAILURE (retval, "schemata");
+		return retval;
 	}
 	case 't': 
 		if ((tname[1] == 'a') && (tname[2] == 'b') && (tname[3] == 'l') && (tname[4] == 'e') && (tname[5] == 's')) {
 			/* _tables, params: 
-			 *  - none
-			 *  - @table_schema
-			 *  - @table_schema AND @table_name
+			 *  -0- @table_catalog, @table_schema, @table_name
+			 *  -1- @table_catalog, @table_schema
 			 */
-			const GValue *p_table_schema = NULL;
-			const GValue *p_table_name = NULL;
-			if (check_parameters (context, error, 3,
-					      &p_table_schema, G_TYPE_STRING,
-					      &p_table_name, G_TYPE_STRING, NULL,
-					      "table_schema", &p_table_schema, "table_name", &p_table_name, NULL,
-					      "table_schema", &p_table_schema, NULL,
-					      NULL) < 0)
+			const GValue *catalog = NULL;
+			const GValue *schema = NULL;
+			const GValue *name = NULL;
+			gint i;
+			i = check_parameters (context, error, 2,
+					      &catalog, G_TYPE_STRING,
+					      &schema, G_TYPE_STRING,
+					      &name, G_TYPE_STRING, NULL,
+					      "table_catalog", &catalog, "table_schema", &schema, "table_name", &name, NULL,
+					      "table_catalog", &catalog, "table_schema", &schema, NULL);
+			if (i < 0)
 				return FALSE;
 			
 			ASSERT_TABLE_NAME (tname, "tables");
-			if (p_table_schema) {
-				if (!PROV_CLASS (provider)->meta_funcs.tables_views_s) {
-					WARN_METHOD_NOT_IMPLEMENTED (provider, "tables_views_s");
-					break;
-				}
-				return PROV_CLASS (provider)->meta_funcs.tables_views_s (provider, cnc, store, context, error, 
-											 p_table_schema, p_table_name);
-			}
-			else {
-				if (!PROV_CLASS (provider)->meta_funcs.tables_views) {
-					WARN_METHOD_NOT_IMPLEMENTED (provider, "tables_views");
-					break;
-				}
-				return PROV_CLASS (provider)->meta_funcs.tables_views (provider, cnc, store, context, error);
+			if (!PROV_CLASS (provider)->meta_funcs.tables_views) {
+				WARN_METHOD_NOT_IMPLEMENTED (provider, "tables_views");
+				break;
 			}
+			retval = PROV_CLASS (provider)->meta_funcs.tables_views (provider, cnc, store, context, error, 
+										 catalog, schema, name);
+			WARN_META_UPDATE_FAILURE (retval, "tables_views");
+			return retval;
 		}
 		else if ((tname[1] == 'a') && (tname[2] == 'b') && (tname[3] == 'l') && (tname[4] == 'e') && 
 			 (tname[5] == '_') && (tname[6] == 'c')) {
 			/* _tables_constraints, params: 
-			 *  - none
-			 *  - @table_schema AND @table_name
+			 *  -0- @table_catalog, @table_schema, @table_name, @constraint_name
+			 *  -1- @table_catalog, @table_schema, @table_name
 			 */
-			const GValue *p_table_schema = NULL;
-			const GValue *p_table_name = NULL;
-			if (check_parameters (context, error, 3,
-					      &p_table_schema, G_TYPE_STRING,
-					      &p_table_name, G_TYPE_STRING, NULL,
-					      "table_schema", &p_table_schema, "table_name", &p_table_name, NULL,
-					      NULL) < 0)
+			const GValue *catalog = NULL;
+			const GValue *schema = NULL;
+			const GValue *tabname = NULL;
+			const GValue *cname = NULL;
+			gint i;
+			i = check_parameters (context, error, 2,
+					      &catalog, G_TYPE_STRING,
+					      &schema, G_TYPE_STRING,
+					      &cname, G_TYPE_STRING,
+					      &tabname, G_TYPE_STRING, NULL,
+					      "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, "constraint_name", &cname, NULL,
+					      "table_catalog", &catalog, "table_schema", &schema, "table_name", &tabname, NULL);
+
+			if (i < 0)
 				return FALSE;
 			
 			ASSERT_TABLE_NAME (tname, "table_constraints");
-			if (p_table_schema) {
-				if (!PROV_CLASS (provider)->meta_funcs.constraints_tab_s) {
-					WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_tab_s");
-					break;
-				}
-				return PROV_CLASS (provider)->meta_funcs.constraints_tab_s (provider, cnc, store, context, error, 
-											    p_table_schema, p_table_name);
-			}
-			else {
-				if (!PROV_CLASS (provider)->meta_funcs.constraints_tab) {
-					WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_tab");
-					break;
-				}
-				return PROV_CLASS (provider)->meta_funcs.constraints_tab (provider, cnc, store, context, error);
+			if (!PROV_CLASS (provider)->meta_funcs.constraints_tab) {
+				WARN_METHOD_NOT_IMPLEMENTED (provider, "constraints_tab");
+				break;
 			}
+			retval = PROV_CLASS (provider)->meta_funcs.constraints_tab (provider, cnc, store, context, error,
+										    catalog, schema, tabname, cname);
+			WARN_META_UPDATE_FAILURE (retval, "constraints_tab");
+			return retval;
 		}
 		break;
 	default:
@@ -1969,15 +1973,26 @@
 	gboolean            error_set;
 } DetailledCallbackData;
 
-static void
+static GError *
 suggest_update_cb_detailled (GdaMetaStore *store, GdaMetaContext *suggest, DetailledCallbackData *data)
 {
-	if (data->error_set)
-		return;
-	if (!local_meta_update (data->prov, data->cnc, suggest, data->error))
+	if (data->error && *(data->error))
+		return *(data->error);
+
+	if (!local_meta_update (data->prov, data->cnc, suggest, data->error)) {
 		data->error_set = TRUE;
+
+		if (! (*(data->error)))
+			g_set_error (data->error, 0, 0,
+				     _("Meta update error"));
+
+		return *(data->error);
+	}
+	return NULL;
 }
 
+static gboolean gda_connection_update_meta_clean_first = TRUE;
+
 /**
  * gda_connection_update_meta_store
  * @cnc: a #GdaConnection object.
@@ -2003,48 +2018,48 @@
 	g_assert (store);
 
 	/* prepare local context */
-	if (!context) {
-		GSList *tables, *list;
-		tables = gda_meta_store_get_schema_tables (store);
-		for (list = tables; list; list = list->next) {
-			GdaMetaContext lcontext;
-			memset (&lcontext, 0, sizeof (GdaMetaContext));
-			lcontext.table_name = (gchar *) list->data;
-			if (!local_meta_update (cnc->priv->provider_obj, cnc, &lcontext, error)) {
-				retval = FALSE;
-				break;
-			}
-		}
-		g_slist_free (tables);
-	}
-	else {
-		GdaMetaContext lcontext;
+	GdaMetaContext lcontext;
+	if (context) {
 		lcontext = *context;
 		/* alter local context because "_tables" and "_views" always go together so only
 		   "_tables" should be updated and providers should always update "_tables" and "_views"
 		*/
 		if (!strcmp (lcontext.table_name, "_views"))
 			lcontext.table_name = "_tables";
-
-		/* actual update */
-		gulong signal_id;
-		DetailledCallbackData cbd;
-		GError *lerror = NULL;
-		
-		cbd.prov = cnc->priv->provider_obj;
-		cbd.cnc = cnc;
-		cbd.error = &lerror;
-		cbd.error_set = FALSE;
-		signal_id = g_signal_connect (store, "suggest_update",
-					      G_CALLBACK (suggest_update_cb_detailled), &cbd);
-		
-		retval = local_meta_update (cnc->priv->provider_obj, cnc, &lcontext, error);
-		
-		g_signal_handler_disconnect (store, signal_id);
-		if (cbd.error_set) {
+	}
+	else {
+		memset (&lcontext, 0, sizeof (GdaMetaContext));
+		lcontext.table_name = "_builtin_data_types";
+		if (!gda_connection_update_meta_store (cnc, &lcontext, error))
+			return FALSE;
+		lcontext.table_name = "_udt";
+		if (!gda_connection_update_meta_store (cnc, &lcontext, error))
+			return FALSE;
+		lcontext.table_name = "_information_schema_catalog_name";
+		if (!gda_connection_update_meta_store (cnc, &lcontext, error))
+			return FALSE;
+		return TRUE;
+	}
+	
+	/* actual update */
+	gulong signal_id;
+	DetailledCallbackData cbd;
+	GError *lerror = NULL;
+	
+	cbd.prov = cnc->priv->provider_obj;
+	cbd.cnc = cnc;
+	cbd.error = &lerror;
+	cbd.error_set = FALSE;
+	signal_id = g_signal_connect (store, "suggest_update",
+				      G_CALLBACK (suggest_update_cb_detailled), &cbd);
+	
+	retval = local_meta_update (cnc->priv->provider_obj, cnc, &lcontext, NULL);
+	
+	g_signal_handler_disconnect (store, signal_id);
+	if (cbd.error_set) {
+		if (lerror)
 			g_propagate_error (error, lerror);
-			retval = FALSE;
-		}
+		retval = FALSE;
 	}
 
 	return retval;

Modified: trunk/libgda/gda-connection.h
==============================================================================
--- trunk/libgda/gda-connection.h	(original)
+++ trunk/libgda/gda-connection.h	Wed Mar 12 21:18:24 2008
@@ -194,6 +194,7 @@
 gchar               *gda_connection_value_to_sql_string  (GdaConnection *cnc, GValue *from);
 
 gboolean             gda_connection_supports_feature     (GdaConnection *cnc, GdaConnectionFeature feature);
+GdaMetaStore        *gda_connection_get_meta_store       (GdaConnection *cnc);
 gboolean             gda_connection_update_meta_store    (GdaConnection *cnc, GdaMetaContext *context, GError **error);
 GdaDataModel        *gda_connection_get_meta_store_data  (GdaConnection *cnc, GdaConnectionMetaType meta_type,
 							  GError **error, gint nb_filters, ...);

Modified: trunk/libgda/gda-data-model-import.c
==============================================================================
--- trunk/libgda/gda-data-model-import.c	(original)
+++ trunk/libgda/gda-data-model-import.c	Wed Mar 12 21:18:24 2008
@@ -1186,7 +1186,7 @@
 				xmlFree (str);
 			}
 			str = (gchar*)xmlTextReaderGetAttribute (reader, (xmlChar*)"nullok");
-			spec->nullok = TRUE;
+			spec->nullok = FALSE;
 			if (str) {
 				spec->nullok = ((*str == 't') || (*str == 'T')) ? TRUE : FALSE;
 				xmlFree (str);

Modified: trunk/libgda/gda-data-model.c
==============================================================================
--- trunk/libgda/gda-data-model.c	(original)
+++ trunk/libgda/gda-data-model.c	Wed Mar 12 21:18:24 2008
@@ -1548,26 +1548,21 @@
 			break;
 		}
 
+		gboolean nullforced = FALSE;
 		isnull = (gchar*)xmlGetProp (xml_field, BAD_CAST "isnull");
 		if (isnull) {
-			if ((*isnull == 'f') || (*isnull == 'F')) {
-				g_free (isnull);
-				isnull = NULL;
-			}
+			if ((*isnull == 't') || (*isnull == 't'))
+				nullforced = TRUE;
+			g_free (isnull);
 		}
 
-		if (!isnull) {
+		if (!nullforced) {
 			value = g_new0 (GValue, 1);
 			if (!gda_value_set_from_string (value, (gchar*)xmlNodeGetContent (xml_field), gdatype)) {
 				g_free (value);
-				g_set_error (error, 0, 0, _("Cannot interpret string as a valid %s value"), 
-					     gda_g_type_to_string (gdatype));
-				retval = FALSE;
-				break;
+				value = gda_value_new_null ();
 			}
 		}
-		else
-			g_free (isnull);
 
 		g_ptr_array_index (values, pos) = value;
 		if (this_lang)

Modified: trunk/libgda/gda-decl.h
==============================================================================
--- trunk/libgda/gda-decl.h	(original)
+++ trunk/libgda/gda-decl.h	Wed Mar 12 21:18:24 2008
@@ -98,6 +98,19 @@
 typedef struct _GdaSqlParserPrivate GdaSqlParserPrivate;
 
 /*
+ * Meta data
+ */
+typedef struct _GdaMetaStore        GdaMetaStore;
+typedef struct _GdaMetaStoreClass   GdaMetaStoreClass;
+typedef struct _GdaMetaStorePrivate GdaMetaStorePrivate;
+typedef struct _GdaMetaStoreClassPrivate GdaMetaStoreClassPrivate;
+
+typedef struct _GdaMetaStruct        GdaMetaStruct;
+typedef struct _GdaMetaStructClass   GdaMetaStructClass;
+typedef struct _GdaMetaStructPrivate GdaMetaStructPrivate;
+
+
+/*
  * Win32 adaptations
  */
 #ifdef G_OS_WIN32

Modified: trunk/libgda/gda-easy.c
==============================================================================
--- trunk/libgda/gda-easy.c	(original)
+++ trunk/libgda/gda-easy.c	Wed Mar 12 21:18:24 2008
@@ -373,16 +373,11 @@
 	    
 		if (!gda_server_operation_load_data_from_xml (op, root, error)) {
 			/* error */
-			g_object_unref (op);
-			xmlFreeDoc(parameters);
 			retval = FALSE;
 		}
-		else {
-			if (gda_server_provider_perform_operation (server, cnc, op, error))
-				/* error */
-				g_object_unref (op);
-		        xmlFreeDoc(parameters);
-			return FALSE;
+		else if (!gda_server_provider_perform_operation (server, cnc, op, error)) {
+			/* error */
+			retval = FALSE;
 		}
 		g_object_unref (op);
 		xmlFreeDoc(parameters);

Modified: trunk/libgda/gda-marshal.list
==============================================================================
--- trunk/libgda/gda-marshal.list	(original)
+++ trunk/libgda/gda-marshal.list	Wed Mar 12 21:18:24 2008
@@ -40,3 +40,4 @@
 VOID:ENUM,POINTER
 BOOLEAN:INT
 BOOLEAN:INT,INT
+POINTER:POINTER

Modified: trunk/libgda/gda-meta-store.c
==============================================================================
--- trunk/libgda/gda-meta-store.c	(original)
+++ trunk/libgda/gda-meta-store.c	Wed Mar 12 21:18:24 2008
@@ -35,6 +35,8 @@
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 #include <libgda/gda-util.h>
+#include <libgda/gda-meta-struct.h>
+#include <libgda/gda-connection.h>
 
 /*
  * Main static functions
@@ -63,7 +65,8 @@
 enum {
 	STMT_GET_VERSION,
 	STMT_SET_VERSION,
-	
+	STMT_DEL_ATT_VALUE,
+	STMT_SET_ATT_VALUE,
 	STMT_LAST
 } PreStmtType;
 
@@ -191,6 +194,9 @@
 	GdaConnection *cnc;
 	gint           version;
 	gboolean       schema_ok;
+
+	GSList        *custom_db_objects; /* list of DbObject structures */
+	GHashTable    *custom_db_objects_hash; /* key = table name, value = a DbObject structure */
 };
 
 static void db_object_free    (DbObject *dbobj);
@@ -281,19 +287,50 @@
 		return TRUE;
 }
 
+static gboolean
+suggest_update_accumulator (GSignalInvocationHint *ihint,
+			    GValue *return_accu,
+			    const GValue *handler_return,
+			    gpointer data)
+{
+        GError *error;
+
+        error = g_value_get_pointer (handler_return);
+        g_value_set_pointer (return_accu, error);
+
+        return error ? FALSE : TRUE; /* stop signal if 'thisvalue' is FALSE */
+}
+
+static GError *
+m_suggest_update (GdaMetaStore *store, GdaMetaContext *suggest)
+{
+        return NULL; /* defaults allows update suggest */
+}
+
 static void
 gda_meta_store_class_init (GdaMetaStoreClass *klass) {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	
 	parent_class = g_type_class_peek_parent (klass);
 	
+	/**
+	 * GdaMetaStore::suggest-update:
+	 * @store: the #GdaMetaStore instance that emitted the signal
+	 * @suggest: the suggested update, as a #GdaMetaContext structure
+	 *
+	 * This signal is emitted when the contents of a table should be updated (data updated or inserted; 
+	 * deleting data is done automatically).
+	 *
+	 * Returns: a new #GError error structure if there was an error when processing the
+	 * signal, or %NULL if signal propagation should continue
+	 **/
 	gda_meta_store_signals[SUGGEST_UPDATE] =
 		g_signal_new ("suggest_update",
 		G_TYPE_FROM_CLASS (object_class),
-		G_SIGNAL_RUN_FIRST,
+		G_SIGNAL_RUN_LAST,
 		G_STRUCT_OFFSET (GdaMetaStoreClass, suggest_update),
-		NULL, NULL,
-		gda_marshal_VOID__POINTER, G_TYPE_NONE,
+		suggest_update_accumulator, NULL,
+		gda_marshal_POINTER__POINTER, G_TYPE_POINTER,
 		1, G_TYPE_POINTER);
 	gda_meta_store_signals[META_CHANGED] =
 		g_signal_new ("meta_changed",
@@ -304,7 +341,7 @@
 		gda_marshal_VOID__POINTER, G_TYPE_NONE,
 		1, G_TYPE_POINTER);
 	
-	klass->suggest_update = NULL;
+	klass->suggest_update = m_suggest_update;
 	klass->meta_changed = NULL;
 	
 	/* Properties */
@@ -337,7 +374,14 @@
 	klass->cpriv->prep_stmts[STMT_GET_VERSION] =
 		compute_prepared_stmt (klass->cpriv->parser, 
 				       "SELECT att_value FROM _attributes WHERE att_name='_schema_version'");
+	klass->cpriv->prep_stmts[STMT_DEL_ATT_VALUE] =
+		compute_prepared_stmt (klass->cpriv->parser, 
+				       "DELETE FROM _attributes WHERE att_name = ##name::string");
+	klass->cpriv->prep_stmts[STMT_SET_ATT_VALUE] =
+		compute_prepared_stmt (klass->cpriv->parser, 
+				       "INSERT INTO _attributes VALUES (##name::string, ##value::string::null)");
 
+/*#define GDA_DEBUG_GRAPH*/
 #ifdef GDA_DEBUG_GRAPH
 #define INFORMATION_SCHEMA_GRAPH_FILE "information_schema.dot"
 	GString *string;
@@ -353,7 +397,7 @@
 			g_string_append_printf (string, "%s [ shape = ellipse ];\n", dbo->obj_name);
 			break;
 		default:
-			g_string_append_printf (string, "%s [ shape = diamond ];\n", dbo->obj_name);
+			g_string_append_printf (string, "%s [ shape = note ];\n", dbo->obj_name);
 			break;
 		}
 
@@ -385,6 +429,9 @@
 	store->priv->cnc = NULL;
 	store->priv->schema_ok = FALSE;
 	store->priv->version = 0;
+
+	store->priv->custom_db_objects = NULL;
+	store->priv->custom_db_objects_hash = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
 static GObject *
@@ -496,6 +543,11 @@
 	
 	store = GDA_META_STORE (object);
 	if (store->priv) {
+		/* custom db objects */
+		g_hash_table_destroy (store->priv->custom_db_objects_hash);
+		g_slist_foreach (store->priv->custom_db_objects, (GFunc) db_object_free, NULL);
+		g_slist_free (store->priv->custom_db_objects);
+
 		/* internal connection */
 		if (store->priv->cnc) {
 			g_object_unref (G_OBJECT (store->priv->cnc));
@@ -723,15 +775,25 @@
 		if (! gda_server_operation_set_value_at (op, repl ? repl : "string", error,
 							 "/FIELDS_A/@COLUMN_TYPE/%d", index))
 			goto onerror;
+		if (! gda_server_operation_set_value_at (op, NULL, error,
+							 "/FIELDS_A/@COLUMN_SIZE/%d", index))
+			goto onerror;
 		if (! gda_server_operation_set_value_at (op, tcol->nullok ? "FALSE" : "TRUE", error,
 							 "/FIELDS_A/@COLUMN_NNUL/%d", index))
 			goto onerror;
-		repl = provider_specific_match (specific_hash, prov, NULL, "/FIELDS_A/@COLUMN_PKEY");
+		if (! gda_server_operation_set_value_at (op, "FALSE", error,
+							 "/FIELDS_A/@COLUMN_AUTOINC/%d", index))
+			goto onerror;
+		repl = provider_specific_match (specific_hash, prov, "dummy", "/FIELDS_A/@COLUMN_PKEY");
 		if (repl) {
 			if (! gda_server_operation_set_value_at (op, tcol->pkey ? "TRUE" : "FALSE", error,
 								 "/FIELDS_A/@COLUMN_PKEY/%d", index))
 				goto onerror;
 		}
+		else {
+			if (! gda_server_operation_set_value_at (op, "FALSE", error, "/FIELDS_A/@COLUMN_PKEY/%d", index))
+				goto onerror;
+		}
 	}
 
 	/* foreign keys */
@@ -1762,7 +1824,7 @@
 				      const gchar *table_name, const gchar *condition, GError **error, 
 				      gint nvalues, const gchar **value_names, const GValue **values);
 static gint find_row_in_model (GdaDataModel *find_in, GdaDataModel *data, gint row,
-			       gint *pk_cols, gint pk_cols_nb, GError **error);
+			       gint *pk_cols, gint pk_cols_nb, gboolean *out_has_changed, GError **error);
 static gboolean gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name, 
 					 GdaDataModel *new_data, const gchar *condition, GError **error, 
 					 gint nvalues, const gchar **value_names, const GValue **values);
@@ -1864,7 +1926,7 @@
 	return retval;
 }
 
-
+/*#define DEBUG_STORE_MODIFY*/
 static gboolean
 gda_meta_store_modify_v (GdaMetaStore *store, const gchar *table_name, 
 			 GdaDataModel *new_data, const gchar *condition, GError **error, 
@@ -1906,7 +1968,7 @@
 	current_n_cols = gda_data_model_get_n_columns (current);
 	rows_to_del = g_new (gboolean, current_n_rows);
 	memset (rows_to_del, TRUE, sizeof (gboolean) * current_n_rows);
-#ifdef GDA_DEBUG_NO
+#ifdef DEBUG_STORE_MODIFY
 	g_print ("CURRENT:\n");
 	gda_data_model_dump (current, stdout);
 #endif
@@ -1916,7 +1978,9 @@
 		started_transaction = gda_connection_begin_transaction (store->priv->cnc, NULL,
 									GDA_TRANSACTION_ISOLATION_UNKNOWN,
 									NULL);
+#ifdef DEBUG_STORE_MODIFY
 		g_print ("------- BEGIN\n");
+#endif
 	}
 
 	/* treat rows to insert / update */
@@ -1924,7 +1988,7 @@
 		gint new_n_rows, new_n_cols;
 		new_n_rows = gda_data_model_get_n_rows (new_data);
 		new_n_cols = gda_data_model_get_n_columns (new_data);
-#ifdef GDA_DEBUG_NO
+#ifdef DEBUG_STORE_MODIFY
 		g_print ("NEW:\n");
 		gda_data_model_dump (new_data, stdout);
 #endif		
@@ -1932,12 +1996,16 @@
 		for (i = 0; i < new_n_rows; i++) {
 			/* find existing row if necessary */
 			gint erow = -1;
-			if (current)
+			gboolean has_changed = FALSE;
+			if (current) {
 				erow = find_row_in_model (current, new_data, i,
-					schema_set->pk_cols_array, schema_set->pk_cols_nb, error);
-			if (erow == -3)
-				/* nothing to do */
-				continue;
+							  schema_set->pk_cols_array, schema_set->pk_cols_nb, &has_changed, 
+							  error);
+#ifdef DEBUG_STORE_MODIFY
+				g_print ("FIND row %d(/%d) returned row %d (%s)\n", i, new_n_rows - 1, erow, 
+					 has_changed ? "CHANGED" : "unchanged");
+#endif
+			}
 			if (erow < -1) {
 				retval = FALSE;
 				goto out;
@@ -1973,8 +2041,8 @@
 			/* execute INSERT or UPDATE statements */
 			if (erow == -1) {
 				/* INSERT: bind INSERT parameters */
-#ifdef GDA_DEBUG_NO
-				g_print ("Insert for new row %d...\n", i);
+#ifdef DEBUG_STORE_MODIFY
+				g_print ("Insert new row %d into table %s\n", i, table_name);
 #endif
 				if (gda_connection_statement_execute_non_select (store->priv->cnc,
 										 schema_set->insert, schema_set->params, 
@@ -1985,7 +2053,7 @@
 				if (change) 
 					change->c_type = GDA_META_STORE_ADD;
 			}
-			else {
+			else if (has_changed) {
 				/* also bind parameters with existing values */
 				for (j = 0; j < current_n_cols; j++) {
 					gchar *pid = g_strdup_printf ("-%d", j);
@@ -2003,8 +2071,8 @@
 					g_free (pid);
 				}
 				/* UPDATE */
-#ifdef GDA_DEBUG_NO
-				g_print ("Update for new row %d (old row was %d)...\n", i, erow);
+#ifdef DEBUG_STORE_MODIFY
+				g_print ("Update for row %d (old row was %d) into table %s\n", i, erow, table_name);
 #endif
 				if (gda_connection_statement_execute_non_select (store->priv->cnc,
 										 schema_set->update, schema_set->params, 
@@ -2016,6 +2084,9 @@
 					change->c_type = GDA_META_STORE_MODIFY;
 				rows_to_del [erow] = FALSE;
 			}
+			else
+				/* row has not changed */
+				rows_to_del [erow] = FALSE;
 
 			/* Dependencies update: reverse_fk_list */
 			GSList *list;
@@ -2032,7 +2103,7 @@
 				for (k = 0; k < tfk->cols_nb; k++) 
 					context.column_values [k] = (GValue*) gda_data_model_get_value_at (new_data, 
 													   tfk->ref_pk_cols_array[k], i);
-#ifdef GDA_DEBUG
+#ifdef DEBUG_STORE_MODIFY
 				g_print ("Suggest update data into table '%s':", tfk->table_info->obj_name);
 				for (k = 0; k < tfk->cols_nb; k++) {
 					gchar *str;
@@ -2042,8 +2113,19 @@
 				}
 				g_print ("\n");
 #endif
-				g_signal_emit (store, gda_meta_store_signals[SUGGEST_UPDATE], 0, &context);
+				GError *suggest_reports_error = NULL;
+				g_signal_emit (store, gda_meta_store_signals[SUGGEST_UPDATE], 0, &context, 
+					       &suggest_reports_error);
 				g_free (context.column_values);
+				if (suggest_reports_error) {
+					/*g_print ("SUGGEST META UPDATE Returned FALSE: %s\n",
+						 suggest_reports_error && suggest_reports_error->message ? 
+						 suggest_reports_error->message : "???");*/
+					retval = FALSE;
+					if (error && !(*error))
+						g_propagate_error (error, suggest_reports_error);
+					goto out;
+				}
 			}
 		}
 	}
@@ -2077,8 +2159,8 @@
 				}
 				g_free (pid);
 			}
-#ifdef GDA_DEBUG_NO
-			g_print ("Delete for existing row %d...\n", i);
+#ifdef DEBUG_STORE_MODIFY
+			g_print ("Delete existing row %d from table %s\n", i, table_name);
 #endif
 			/* reverse_fk_list */
 			GSList *list;
@@ -2112,7 +2194,9 @@
 
 	if (retval && started_transaction) {
 		retval = gda_connection_commit_transaction (store->priv->cnc, NULL, NULL);
+#ifdef DEBUG_STORE_MODIFY
 		g_print ("------- COMMIT\n");
+#endif
 	}
 	if (retval && all_changes) 
 		g_signal_emit (store, gda_meta_store_signals[META_CHANGED], 0, all_changes);
@@ -2127,7 +2211,9 @@
 		g_object_unref (current);
 	if (!retval && started_transaction) {
 		gda_connection_rollback_transaction (store->priv->cnc, NULL, NULL);
+#ifdef DEBUG_STORE_MODIFY
 		g_print ("------- ROLLBACK\n");
+#endif
 	}
 	return retval;
 }
@@ -2136,13 +2222,14 @@
  * Find the row in @find_in from the values of @data at line @row, and columns pointed by
  * the values of @pk_cols
  *
- * Returns: -3 if found and no change need to be made, 
+ * Returns: 
  *          -2 on error, 
  *          -1 if not found, 
- *          >0 if found and changes need to be made
+ *          >=0 if found (if changes need to be made, then @out_has_changed is set to TRUE).
  */
 static gint
-find_row_in_model (GdaDataModel *find_in, GdaDataModel *data, gint row, gint *pk_cols, gint pk_cols_nb, GError **error) {
+find_row_in_model (GdaDataModel *find_in, GdaDataModel *data, gint row, gint *pk_cols, gint pk_cols_nb, 
+		   gboolean *out_has_changed, GError **error) {
 	gint i, erow;
 	GSList *values = NULL;
 	
@@ -2165,27 +2252,12 @@
 				const GValue *v1, *v2;
 				v1 = gda_data_model_get_value_at (find_in, i, erow);
 				v2 = gda_data_model_get_value_at (data, i, row);
-				if (((!v1 || gda_value_is_null (v1)) && v2) || 
-				    (v1 && (!v2 || gda_value_is_null (v2)))) {
+				if (gda_value_compare_ext (v1, v2)) {
 					changed = TRUE;
 					break;
 				}
-				else if (v1 && v2) {
-					if (G_VALUE_TYPE (v1) != G_VALUE_TYPE (v2)) {
-						g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_MODIFY_CONTENTS_ERROR,
-							     _("Data types differ for column %d (expected type '%s' and got '%s')"),
-							     i, g_type_name (G_VALUE_TYPE (v1)), g_type_name (G_VALUE_TYPE (v2)));
-						erow = -2;
-						break;
-					}
-					if (gda_value_compare (v1, v2)) {
-						changed = TRUE;
-						break;
-					}
-				}
 			}
-			if (!changed && (erow >= 0))
-				erow = -3;
+			*out_has_changed = changed;
 		}
 	}
 	
@@ -2363,71 +2435,336 @@
 }
 
 /**
- * gda_meta_store_get_depending_tables
+ * gda_meta_store_schema_get_tables
  * @store: a #GdaMetaStore object
- * @table_name: the name of a table present in @store
  *
- * Get a list of the tables which depend on the table named @table_name.
+ * Get an ordered list of the tables @store knows about. The tables are ordered in a way that tables dependencies
+ * are respected: if table B has a foreign key on table A, then table A will be listed before table B in the returned
+ * list.
  *
  * Returns: a new list of tables names (as gchar*), the list must be freed when no longer needed, 
  * but the strings present in the list must not be modified.
  */
 GSList *
-gda_meta_store_get_depending_tables (GdaMetaStore *store, const gchar *table_name)
+gda_meta_store_schema_get_tables (GdaMetaStore *store)
 {
 	GSList *list, *ret;
 	GdaMetaStoreClass *klass;
-	DbObject *dbobj;
-	TableInfo *tinfo;
 
 	g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
-	g_return_val_if_fail (table_name && *table_name, NULL);
 
 	klass = (GdaMetaStoreClass *) G_OBJECT_GET_CLASS (store);
-	dbobj = g_hash_table_lookup (klass->cpriv->db_objects_hash, table_name);
-	if (!dbobj) {
-		g_warning ("Table '%s' is not known by the GdaMetaStore", table_name);
-		return NULL;
+	for (ret = NULL, list = klass->cpriv->db_objects; list; list = list->next) {
+		DbObject *dbobj = DB_OBJECT (list->data);
+		if (dbobj->obj_type == GDA_SERVER_OPERATION_CREATE_TABLE)
+			ret = g_slist_prepend (ret, dbobj->obj_name);
 	}
-	if (dbobj->obj_type != GDA_SERVER_OPERATION_CREATE_TABLE) {
-		g_warning ("Table '%s' is not a database table in the GdaMetaStore", table_name);
+
+	return g_slist_reverse (ret);
+}
+
+
+/**
+ * gda_meta_store_schema_get_structure
+ * @store: a #GdaMetaStore object
+ * @error: a place to store errors, or %NULL
+ *
+ * Creates a new #GdaMetaStruct object representing @store's interal database structure.
+ *
+ * Returns: a new #GdaMetaStruct object, or %NULL if an error occurred
+ */
+GdaMetaStruct *
+gda_meta_store_schema_get_structure (GdaMetaStore *store, GError **error)
+{
+	GdaMetaStruct *mstruct;
+	GdaMetaStore *pstore;
+	GdaDataModel *model;
+	gint i, nrows;
+
+	g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
+
+	/* make sure the private connection's meta store is up to date */
+	if (! gda_connection_update_meta_store (store->priv->cnc, NULL, error))
+		return NULL;
+
+	/* create a GdaMetaStruct */
+	pstore = gda_connection_get_meta_store (store->priv->cnc);
+	model = gda_meta_store_extract (pstore, "SELECT table_catalog, table_schema, table_name FROM _tables", error, NULL);
+	if (!model)
 		return NULL;
+
+	mstruct = gda_meta_struct_new (GDA_META_STRUCT_FEATURE_ALL);
+	nrows = gda_data_model_get_n_rows (model);
+	for (i = 0; i < nrows; i++) {
+		if (!gda_meta_struct_complement (mstruct, pstore, GDA_META_DB_UNKNOWN,
+						 gda_data_model_get_value_at (model, 0, i),
+						 gda_data_model_get_value_at (model, 1, i),
+						 gda_data_model_get_value_at (model, 2, i), error)) {
+			g_object_unref (mstruct);
+			g_object_unref (model);
+			return NULL;
+		}
 	}
+	g_object_unref (model);
 
-	tinfo = TABLE_INFO (dbobj);
-	for (ret = NULL, list = tinfo->reverse_fk_list; list; list = list->next) {
-		TableFKey *tfk = (TableFKey*) list->data;
-		ret = g_slist_prepend (ret, tfk->table_info->obj_name);
+	/* complement the meta struct with some info about dependencies */
+	GSList *list;
+	GdaMetaStoreClass *klass;
+
+	klass = (GdaMetaStoreClass *) G_OBJECT_GET_CLASS (pstore);
+	for (list = klass->cpriv->db_objects; list; list = list->next) {
+		DbObject *dbobj = DB_OBJECT (list->data);
+		if (dbobj->obj_type == GDA_SERVER_OPERATION_CREATE_TABLE) {
+			GdaMetaDbObject *mdbo;
+			GSList *dep_list;
+			GValue *value;
+
+			g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), dbobj->obj_name);
+			mdbo = gda_meta_struct_get_db_object (mstruct, NULL, NULL, value);
+			gda_value_free (value);
+			if (!mdbo)
+				continue;
+			for (dep_list = dbobj->depend_list; dep_list; dep_list = dep_list->next) {
+				GdaMetaDbObject *dep_mdbo;
+				g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), DB_OBJECT (dep_list->data)->obj_name);
+				dep_mdbo = gda_meta_struct_get_db_object (mstruct, NULL, NULL, value);
+				gda_value_free (value);
+				if (dep_mdbo && !g_slist_find (mdbo->depend_list, dep_mdbo)) {
+					/* FIXME: dependencies are added using the mdbo->depend_list list, and not as
+					 * real foreign key */
+					mdbo->depend_list = g_slist_append (mdbo->depend_list, dep_mdbo);
+				}
+			}
+		}
 	}
+	
+	return mstruct;
+}
 
-	return g_slist_reverse (ret);
+/**
+ * gda_meta_store_get_attribute_value
+ * @store: a #GdaMetaStore object
+ * @att_name: name of the attribute to get
+ * @att_value: the place to store the attribute value
+ * @error: a place to store errors, or %NULL
+ *
+ * The #GdaMetaStore object maintains a list of (name,value) attributes (attributes names starting with a '_'
+ * character are for intarnal use only and cannot be altered). This method and the gda_meta_store_set_attribute_value()
+ * method allows the user to add, set or remove attributes specific to their usage.
+ * 
+ * This method allows to get the value of a attribute stored in @store. The returned attribute value is 
+ * placed at @att_value, the caller is responsible to free that string. 
+ *
+ * If there is no attribute named @att_name then @att_value is set to %NULL
+ * and @error will contain the GDA_META_STORE_ATTRIBUTE_NOT_FOUND_ERROR error code, and FALSE is returned.
+ *
+ * Returns: TRUE if no error occurred
+ */
+gboolean
+gda_meta_store_get_attribute_value (GdaMetaStore *store, const gchar *att_name, gchar **att_value, GError **error)
+{
+	GdaDataModel *model;
+	GValue *value;
+	gint nrows;
+	g_return_val_if_fail (GDA_IS_META_STORE (store), FALSE);
+	g_return_val_if_fail (att_name && *att_name, FALSE);
+	g_return_val_if_fail (att_value, FALSE);
+
+	*att_value = NULL;
+	g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), att_name);
+	model = gda_meta_store_extract (store, "SELECT att_value FROM _attributes WHERE att_name = ##n::string", error,
+					"n", value, NULL);
+	gda_value_free (value);
+	if (!model)
+		return FALSE;
+	nrows = gda_data_model_get_n_rows (model);
+	if (nrows < 1) 
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_ATTRIBUTE_NOT_FOUND_ERROR,
+			     _("Attribute '%s' not found"), att_name);
+	else if (nrows > 1) 
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_ATTRIBUTE_ERROR,
+			     _("Attribute '%s' has %d values"), att_name, nrows);
+	else {
+		value = (GValue*) gda_data_model_get_value_at (model, 0, 0);
+		if (value && (G_VALUE_TYPE (value) == G_TYPE_STRING)) {
+			const gchar *val;
+			val = g_value_get_string (value);
+			if (val) 
+				*att_value = g_strdup (val);
+		}
+		return TRUE;
+	}
+	return FALSE;
 }
 
 /**
- * gda_meta_store_get_schema_tables
+ * gda_meta_store_set_attribute_value
  * @store: a #GdaMetaStore object
+ * @att_name: name of the attribute to set
+ * @att_value: value of the attribute to set, or %NULL to unset the attribute
+ * @error: a place to store errors, or %NULL
  *
- * Get an ordered list of the tables @store knows about. The tables are ordered in a way that tables dependencies
- * are respected: if table B has a foreign key on table A, then table A will be listed before table B in the returned
- * list.
+ * Set the value of the attribute named @att_name to @att_value; see gda_meta_store_get_attribute_value() for
+ * more information.
  *
- * Returns: a new list of tables names (as gchar*), the list must be freed when no longer needed, 
- * but the strings present in the list must not be modified.
+ * Returns: TRUE if no error occurred
  */
-GSList *
-gda_meta_store_get_schema_tables (GdaMetaStore *store)
+gboolean
+gda_meta_store_set_attribute_value (GdaMetaStore *store, const gchar *att_name, 
+				    const gchar *att_value, GError **error)
 {
-	GSList *list, *ret;
 	GdaMetaStoreClass *klass;
+	static GdaSet *set = NULL;
+	gboolean started_transaction = FALSE;
 
-	g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
+	g_return_val_if_fail (GDA_IS_META_STORE (store), FALSE);
+	g_return_val_if_fail (att_name && *att_name, FALSE);
+
+	if (*att_name == '_') {
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_ATTRIBUTE_ERROR,
+			     _("Attributes names starting with a '_' are reserved for internal usage"));
+		return FALSE;
+	}
 
 	klass = (GdaMetaStoreClass *) G_OBJECT_GET_CLASS (store);
-	for (ret = NULL, list = klass->cpriv->db_objects; list; list = list->next) {
-		DbObject *dbobj = DB_OBJECT (list->data);
-		if (dbobj->obj_type == GDA_SERVER_OPERATION_CREATE_TABLE)
-			ret = g_slist_prepend (ret, dbobj->obj_name);
+	if (!set) {
+		if (!gda_statement_get_parameters (klass->cpriv->prep_stmts [STMT_SET_ATT_VALUE], &set, error))
+			return FALSE;
 	}
 
-	return g_slist_reverse (ret);
+	if (!gda_set_set_holder_value (set, "name", att_name)) {
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_ATTRIBUTE_ERROR,
+			     _("Internal GdaMetaStore error"));
+		return FALSE;
+	}
+	
+	/* start a transaction if possible */
+	if (! gda_connection_get_transaction_status (store->priv->cnc)) 
+		started_transaction = gda_connection_begin_transaction (store->priv->cnc, NULL,
+									GDA_TRANSACTION_ISOLATION_UNKNOWN,
+									NULL);
+	else
+		g_warning (_("Could not start a transaction because one already started, this could lead to GdaMetaStore "
+			     "attributes problems"));
+
+	/* delete existing attribute */
+	if (gda_connection_statement_execute_non_select (store->priv->cnc, 
+							 klass->cpriv->prep_stmts [STMT_DEL_ATT_VALUE], set,
+							 NULL, error) == -1)
+		goto onerror;
+
+	if (att_value) {
+		/* set new attribute */
+		if (!gda_set_set_holder_value (set, "value", att_value)) {
+			g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_ATTRIBUTE_ERROR,
+				     _("Internal GdaMetaStore error"));
+			goto onerror;
+		}
+		if (gda_connection_statement_execute_non_select (store->priv->cnc, 
+								 klass->cpriv->prep_stmts [STMT_SET_ATT_VALUE], set,
+								 NULL, error) == -1)
+			goto onerror;
+	}
+	if (started_transaction)
+		gda_connection_commit_transaction (store->priv->cnc, NULL, NULL);
+	return TRUE;
+
+ onerror:
+	if (started_transaction)
+		gda_connection_rollback_transaction (store->priv->cnc, NULL, NULL);
+	return FALSE;
+}
+
+/**
+ * gda_meta_store_schema_add_custom_object
+ * @store: a #GdaMetaStore object
+ * @xml_description: an XML description of the table or view to add to @store
+ * @error: a place to store errors, or %NULL
+ *
+ * The internal database used by @store can be 'augmented' with some user-defined database objects
+ * (such as tables or views). This method allows one to add a new database object.
+ *
+ * If the internal database already contains the object, then:
+ * <itemizedlist>
+ *   <listitem><para>if the object is equal to the provided description then TRUE is returned</para></listitem>
+ *   <listitem><para>if the object exists but differs from the provided description, then FALSE is returned,
+ *      with the GDA_META_STORE_SCHEMA_OBJECT_CONFLICT_ERROR error code</para></listitem>
+ * </itemizedlist>
+ *
+ * Returns: TRUE if the new object has sucessfully been added
+ */
+gboolean
+gda_meta_store_schema_add_custom_object (GdaMetaStore *store, const gchar *xml_description, GError **error)
+{
+	xmlDocPtr doc;
+	xmlNodePtr node;
+	GdaMetaStoreClass *klass;
+	DbObject *dbo = NULL;
+	GValue *value;
+	GdaMetaStore *pstore;
+	GdaMetaStruct *mstruct;
+
+	g_return_val_if_fail (GDA_IS_META_STORE (store), FALSE);
+	g_return_val_if_fail (xml_description && *xml_description, FALSE);
+
+	/* load XML description */
+	doc = xmlParseDoc (BAD_CAST xml_description);
+	if (!doc) {
+		g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR,
+			     _("Could not parse XML description of custom database object to add"));
+		return FALSE;
+	}
+	node = xmlDocGetRootElement (doc);
+
+	klass = (GdaMetaStoreClass *) G_OBJECT_GET_CLASS (store);
+
+	/* create DbObject structure from XML description */
+	/* FIXME: create the DbObject but store it into @store->priv instead of klass->cpriv */
+	if (!strcmp ((gchar *) node->name, "table")) {
+		xmlChar *prop;
+		prop = xmlGetProp (node, BAD_CAST "name");
+		if (!prop) 
+			g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR,
+				     _("Missing custom database object name"));
+		else if (*prop == '_') 
+			g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR,
+				     _("Custom database object names starting with a '_' are reserved for internal usage"));
+		else
+			dbo = create_table_object (klass, node, error);
+	}
+	else if (!strcmp ((gchar *) node->name, "view")) {
+		xmlChar *prop;
+		prop = xmlGetProp (node, BAD_CAST "name");
+		if (!prop) 
+			g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR,
+				     _("Missing custom database object name"));
+		else if (*prop == '_') 
+			g_set_error (error, GDA_META_STORE_ERROR, GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR,
+				     _("Custom database object names starting with a '_' are reserved for internal usage"));
+		else
+			dbo = create_view_object (klass, node, error);
+	}
+
+	xmlFreeDoc (doc);
+
+	if (!dbo) 
+		return FALSE;
+
+	/* check for an already existing database object with the same name */
+	g_print ("Obj name: %s\n", dbo->obj_name);
+
+	/* make sure the private connection's meta store is up to date */
+	if (! gda_connection_update_meta_store (store->priv->cnc, NULL, error))
+		return FALSE;
+
+	/* create a GdaMetaStruct */
+	pstore = gda_connection_get_meta_store (store->priv->cnc);
+	mstruct = gda_meta_struct_new (GDA_META_STRUCT_FEATURE_ALL);
+	g_value_set_string ((value = gda_value_new (G_TYPE_STRING)), dbo->obj_name);
+	if (!gda_meta_struct_complement (mstruct, pstore, GDA_META_DB_UNKNOWN,
+					 NULL, NULL, value, error))
+		return FALSE;
+	gda_value_free (value);
+	
+	return TRUE;
 }

Modified: trunk/libgda/gda-meta-store.h
==============================================================================
--- trunk/libgda/gda-meta-store.h	(original)
+++ trunk/libgda/gda-meta-store.h	Wed Mar 12 21:18:24 2008
@@ -24,6 +24,7 @@
 #include <glib-object.h>
 #include <libgda/gda-enums.h>
 #include <libgda/gda-data-model.h>
+#include <libgda/gda-decl.h>
 
 G_BEGIN_DECLS
 
@@ -32,11 +33,6 @@
 #define GDA_META_STORE_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, gda_meta_store_get_type (), GdaMetaStoreClass)
 #define GDA_IS_META_STORE(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, gda_meta_store_get_type ())
 
-typedef struct _GdaMetaStore        GdaMetaStore;
-typedef struct _GdaMetaStoreClass   GdaMetaStoreClass;
-typedef struct _GdaMetaStorePrivate GdaMetaStorePrivate;
-typedef struct _GdaMetaStoreClassPrivate GdaMetaStoreClassPrivate;
-
 /* error reporting */
 extern GQuark gda_meta_store_error_quark (void);
 #define GDA_META_STORE_ERROR gda_meta_store_error_quark ()
@@ -46,7 +42,11 @@
 	GDA_META_STORE_UNSUPPORTED_PROVIDER,
 	GDA_META_STORE_INTERNAL_ERROR,
 	GDA_META_STORE_MODIFY_CONTENTS_ERROR,
-	GDA_META_STORE_EXTRACT_SQL_ERROR
+	GDA_META_STORE_EXTRACT_SQL_ERROR,
+	GDA_META_STORE_ATTRIBUTE_NOT_FOUND_ERROR,
+	GDA_META_STORE_ATTRIBUTE_ERROR,
+	GDA_META_STORE_SCHEMA_OBJECT_CONFLICT_ERROR,
+	GDA_META_STORE_SCHEMA_OBJECT_DESCR_ERROR
 } GdaMetaStoreError;
 
 /* 
@@ -87,8 +87,9 @@
 	GdaMetaStoreClassPrivate *cpriv;
 
 	/* signals the changes */
-	void    (*suggest_update)(GdaMetaStore *store, GdaMetaContext *suggest);
-	void    (*meta_changed)  (GdaMetaStore *store, GSList *changes);
+	void     (*reset)         (GdaMetaStore *store, GdaMetaContext *suggest);
+	GError  *(*suggest_update)(GdaMetaStore *store, GdaMetaContext *suggest);
+	void     (*meta_changed)  (GdaMetaStore *store, GSList *changes);
 };
 
 GType             gda_meta_store_get_type                 (void) G_GNUC_CONST;
@@ -98,14 +99,24 @@
 
 GdaConnection    *gda_meta_store_get_internal_connection  (GdaMetaStore *store);
 GdaDataModel     *gda_meta_store_extract                  (GdaMetaStore *store, const gchar *select_sql, GError **error, ...);
-
 gboolean          gda_meta_store_modify                   (GdaMetaStore *store, const gchar *table_name, 
 							   GdaDataModel *new_data, const gchar *condition, GError **error, ...);
 gboolean          gda_meta_store_modify_with_context      (GdaMetaStore *store, GdaMetaContext *context, 
 							   GdaDataModel *new_data, GError **error);
 GdaDataModel     *gda_meta_store_create_modify_data_model (GdaMetaStore *store, const gchar *table_name);
-GSList           *gda_meta_store_get_depending_tables     (GdaMetaStore *store, const gchar *table_name);
-GSList           *gda_meta_store_get_schema_tables        (GdaMetaStore *store);
+
+GdaMetaStruct    *gda_meta_store_schema_get_structure     (GdaMetaStore *store, GError **error);
+
+gboolean          gda_meta_store_get_attribute_value      (GdaMetaStore *store, const gchar *att_name, 
+							   gchar **att_value, GError **error);
+gboolean          gda_meta_store_set_attribute_value      (GdaMetaStore *store, const gchar *att_name, 
+							   const gchar *att_value, GError **error);
+
+gboolean          gda_meta_store_schema_add_custom_object (GdaMetaStore *store, const gchar *xml_description, 
+							   GError **error);
+
+/* TO REMOVE */
+GSList           *gda_meta_store_schema_get_tables        (GdaMetaStore *store);
 
 G_END_DECLS
 

Modified: trunk/libgda/gda-meta-struct.c
==============================================================================
--- trunk/libgda/gda-meta-struct.c	(original)
+++ trunk/libgda/gda-meta-struct.c	Wed Mar 12 21:18:24 2008
@@ -44,6 +44,7 @@
 
 struct _GdaMetaStructPrivate {
 	GHashTable *index; /* key = [catalog].[schema].[name], value = a GdaMetaDbObject */
+	guint       features;
 };
 
 static void gda_meta_db_object_free (GdaMetaDbObject *dbo);
@@ -102,11 +103,11 @@
         object_class->set_property = gda_meta_struct_set_property;
         object_class->get_property = gda_meta_struct_get_property;
         g_object_class_install_property (object_class, PROP_FEATURES,
-					 g_param_spec_int ("fetures", _ ("Features to compute"), NULL, 
-							   GDA_META_STRUCT_FEATURE_ALL, G_MAXINT,
-							   GDA_META_STRUCT_FEATURE_ALL,
-							   (G_PARAM_WRITABLE | G_PARAM_READABLE | 
-							    G_PARAM_CONSTRUCT_ONLY)));
+					 g_param_spec_uint ("features", _ ("Features to compute"), NULL, 
+							    GDA_META_STRUCT_FEATURE_NONE, G_MAXINT,
+							    GDA_META_STRUCT_FEATURE_ALL,
+							    (G_PARAM_WRITABLE | G_PARAM_READABLE | 
+							     G_PARAM_CONSTRUCT_ONLY)));
 
 	/* virtual methods */
 	object_class->finalize = gda_meta_struct_finalize;
@@ -122,13 +123,15 @@
 
 /**
  * gda_meta_struct_new
+ * @features: the kind of information the new #GdaMetaStruct object will compute (the more features, the more time
+ * it takes to run)
  *
  * Returns: the newly created #GdaMetaStruct object
  */
 GdaMetaStruct *
-gda_meta_struct_new (void) 
+gda_meta_struct_new (GdaMetaStructFeature features) 
 {
-	return (GdaMetaStruct*) g_object_new (GDA_TYPE_META_STRUCT, NULL);
+	return (GdaMetaStruct*) g_object_new (GDA_TYPE_META_STRUCT, "features", features, NULL);
 }
 
 static void
@@ -163,7 +166,7 @@
         if (mstruct->priv) {
                 switch (param_id) {
 		case PROP_FEATURES:
-			TO_IMPLEMENT;
+			mstruct->priv->features = g_value_get_uint (value);
 			break;
 		default:
 			break;
@@ -183,7 +186,7 @@
         if (mstruct->priv) {
                 switch (param_id) {
 		case PROP_FEATURES:
-			TO_IMPLEMENT;
+			g_value_set_uint (value, mstruct->priv->features);
 			break;
 		default:
 			break;
@@ -193,7 +196,7 @@
 
 
 static void
-compute_view_dependencies (GdaMetaStruct *mstruct, GdaMetaDbObject *view_dbobj, GdaSqlStatement *sqlst) 
+compute_view_dependencies (GdaMetaStruct *mstruct, GdaMetaStore *store, GdaMetaDbObject *view_dbobj, GdaSqlStatement *sqlst) 
 {	
 	if (sqlst->stmt_type == GDA_SQL_STATEMENT_SELECT) {
 		GdaSqlStatementSelect *selst;
@@ -202,28 +205,51 @@
 		for (targets = selst->from->targets; targets; targets = targets->next) {
 			GdaSqlSelectTarget *t = (GdaSqlSelectTarget *) targets->data;
 			GValue *catalog, *schema, *name;
-			GdaMetaDbObject *ref_obj;
+			GdaMetaDbObject *ref_obj, *tmp_obj;
+			GdaMetaStruct *m2;
+			GValue *vname;
 
 			if (!t->table_name)
 				continue;
-			/* FIXME: compute catalog, schema, name using t->table_name */
-			/*
+			
+			m2 = gda_meta_struct_new (GDA_META_STRUCT_FEATURE_NONE);
+			g_value_set_string ((vname = gda_value_new (G_TYPE_STRING)), t->table_name);
+			if (! (tmp_obj = gda_meta_struct_complement (m2, store, GDA_META_DB_TABLE, NULL, NULL, vname, NULL)))
+				tmp_obj = gda_meta_struct_complement (m2, store, GDA_META_DB_VIEW, NULL, NULL, vname, NULL);
+			gda_value_free (vname);
+
+			if (!tmp_obj) {
+				/* could not find dependency */
+				g_object_unref (m2);
+				continue;
+			}
+
+			/* the dependency exists, and is identified by tmp_obj->obj_catalog, tmp_obj->obj_schema 
+			 * and tmp_obj->obj_name */
+			g_value_set_string ((catalog = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_catalog);
+			g_value_set_string ((schema = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_schema);
+			g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), tmp_obj->obj_name);
 			ref_obj = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
 			if (!ref_obj) {
 				gchar *str;
 				ref_obj = g_new0 (GdaMetaDbObject, 1);
 				ref_obj->obj_type = GDA_META_DB_UNKNOWN;
-				ref_obj->obj_catalog = g_strdup (g_value_get_string (fk_catalog));
-				ref_obj->obj_schema = g_strdup (g_value_get_string (fk_schema));
-				ref_obj->obj_name = g_strdup (g_value_get_string (fk_name));
+				ref_obj->obj_catalog = g_strdup (tmp_obj->obj_catalog);
+				ref_obj->obj_schema = g_strdup (tmp_obj->obj_schema);
+				ref_obj->obj_name = g_strdup (tmp_obj->obj_name);
+
 				mstruct->db_objects = g_slist_append (mstruct->db_objects, ref_obj);
-				str = g_strdup_printf ("%s.%s.%s", g_value_get_string (fk_catalog), 
-						       g_value_get_string (fk_schema), 
-						       g_value_get_string (fk_name));
+				str = g_strdup_printf ("%s.%s.%s", tmp_obj->obj_catalog,
+						       tmp_obj->obj_schema, tmp_obj->obj_name);
 				g_hash_table_insert (mstruct->priv->index, str, ref_obj);
 			}
+			g_assert (ref_obj);
+			g_object_unref (m2);
+			gda_value_free (catalog);
+			gda_value_free (schema);
+			gda_value_free (name);
+
 			view_dbobj->depend_list = g_slist_append (view_dbobj->depend_list, ref_obj);
-			*/
 		}
 	}
 	else if (sqlst->stmt_type == GDA_SQL_STATEMENT_COMPOUND) {
@@ -231,26 +257,30 @@
 		GSList *list;
 		cst = (GdaSqlStatementCompound*) (sqlst->contents);
 		for (list = cst->stmt_list; list; list = list->next)
-			compute_view_dependencies (mstruct, view_dbobj, (GdaSqlStatement*) list->data);
+			compute_view_dependencies (mstruct, store, view_dbobj, (GdaSqlStatement*) list->data);
 	}
 	else
 		g_assert_not_reached ();
 }
 
 static gboolean determine_db_object_from_schema_and_name (GdaMetaStruct *mstruct, GdaMetaStore *store, 
-							  GdaMetaDbObjectType type, GValue **out_catalog,
+							  GdaMetaDbObjectType *int_out_type, GValue **out_catalog,
 							  GValue **out_short_name, GValue **out_full_name,
 							  GValue **out_owner, const GValue *schema, const GValue *name);
 static gboolean determine_db_object_from_short_name (GdaMetaStruct *mstruct, GdaMetaStore *store, 
-						     GdaMetaDbObjectType type, GValue **out_catalog,
+						     GdaMetaDbObjectType *int_out_type, GValue **out_catalog,
 						     GValue **out_schema, GValue **out_name, GValue **out_short_name, 
 						     GValue **out_full_name, GValue **out_owner, const GValue *name);
+static gboolean determine_db_object_from_missing_type (GdaMetaStruct *mstruct, GdaMetaStore *store, 
+						       GdaMetaDbObjectType *out_type, GValue **out_short_name, 
+						       GValue **out_full_name, GValue **out_owner, const GValue *catalog, 
+						       const GValue *schema, const GValue *name);
 
 /**
  * gda_meta_struct_complement
  * @mstruct: a #GdaMetaStruct object
  * @store: the #GdaMetaStore to use
- * @type: the type of object to add
+ * @type: the type of object to add (which can be GDA_META_DB_UNKNOWN)
  * @catalog: the catalog the object belongs to (as a G_TYPE_STRING GValue), or %NULL
  * @schema: the schema the object belongs to (as a G_TYPE_STRING GValue), or %NULL
  * @name: the object's name (as a G_TYPE_STRING GValue), not %NULL
@@ -273,17 +303,18 @@
 			    GError **error)
 {
 	GdaMetaDbObject *dbo = NULL;
+	GdaMetaDbObjectType real_type = type;
 	GValue *real_catalog = NULL, *real_schema = NULL, *real_name = NULL;
 	GValue *short_name = NULL, *full_name=NULL, *owner=NULL;
 
 	g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
-	g_return_val_if_fail (mstruct, NULL);
+	g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
 	g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
 
 	if (!catalog) {
 		if (schema) {
 			g_return_val_if_fail (schema && (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
-			if (! determine_db_object_from_schema_and_name (mstruct, store, type, &real_catalog, 
+			if (! determine_db_object_from_schema_and_name (mstruct, store, &real_type, &real_catalog, 
 									&short_name, &full_name, &owner,
 									schema, name)) {
 				g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
@@ -294,7 +325,7 @@
 			catalog = real_catalog;
 		}
 		else {
-			if (! determine_db_object_from_short_name (mstruct, store, type, &real_catalog, 
+			if (! determine_db_object_from_short_name (mstruct, store, &real_type, &real_catalog, 
 								   &real_schema, &real_name, 
 								   &short_name, &full_name, &owner, name)) {
 				g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
@@ -307,8 +338,19 @@
 			schema = real_schema;
 		}
 	}
-	g_return_val_if_fail (catalog && (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
-	g_return_val_if_fail (schema && (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
+	else if (type == GDA_META_DB_UNKNOWN) {
+		g_return_val_if_fail (catalog && (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
+		g_return_val_if_fail (schema && (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
+
+		if (! determine_db_object_from_missing_type (mstruct, store, &real_type, &short_name, &full_name, &owner,
+							     catalog, schema, name)) {
+			g_set_error (error, GDA_META_STRUCT_ERROR, GDA_META_STRUCT_UNKNOWN_OBJECT_ERROR,
+				     _("Could not find object named '%s.%s.%s'"), g_value_get_string (catalog),
+				     g_value_get_string (schema), g_value_get_string (name));
+			return NULL;
+		}
+	}
+	type = real_type;
 	
 	/* create new GdaMetaDbObject or get already existing one */
 	dbo = gda_meta_struct_get_db_object (mstruct, catalog, schema, name);
@@ -372,7 +414,8 @@
 		mv->is_updatable = g_value_get_boolean (gda_data_model_get_value_at (model, 1, 0));
 
 		/* view's dependencies, from its definition */
-		if (mv->view_def && *mv->view_def) {
+		if ((mstruct->priv->features & GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES) && 
+		    mv->view_def && *mv->view_def) {
 			static GdaSqlParser *parser = NULL;
 			GdaStatement *stmt;
 			const gchar *remain;
@@ -384,7 +427,7 @@
 			     (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_COMPOUND))) {
 				GdaSqlStatement *sqlst;
 				g_object_get (G_OBJECT (stmt), "structure", &sqlst, NULL);
-				compute_view_dependencies (mstruct, dbo, sqlst);
+				compute_view_dependencies (mstruct, store, dbo, sqlst);
 				gda_sql_statement_free (sqlst);
 				g_object_unref (stmt);
 				
@@ -400,10 +443,7 @@
 	}
 	case GDA_META_DB_TABLE: {
 		/* columns */
-		gchar *sql = "SELECT c.column_name, c.data_type, c.gtype, c.is_nullable, t.table_short_name, t.table_full_name, "
-			"c.column_default, t.table_owner FROM _columns as c NATURAL JOIN _tables as t WHERE table_catalog = ##tc::string "
-			"AND table_schema = ##ts::string AND table_name = ##tname::string "
-			"ORDER BY ordinal_position";
+		gchar *sql = "SELECT c.column_name, c.data_type, c.gtype, c.is_nullable, t.table_short_name, t.table_full_name, c.column_default, t.table_owner FROM _columns as c NATURAL JOIN _tables as t WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string ORDER BY ordinal_position";
 		GdaMetaTable *mt;
 		GdaDataModel *model;
 		gint i, nrows;
@@ -448,19 +488,19 @@
 		g_object_unref (model);
 
 		/* primary key */
-		sql = "SELECT constraint_catalog, constraint_schema, constraint_name FROM _table_constraints WHERE constraint_type='PRIMARY KEY' AND table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
+		sql = "SELECT constraint_name FROM _table_constraints WHERE constraint_type='PRIMARY KEY' AND table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
 		model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
 		if (!model) 
 			goto onerror;
 
 		nrows = gda_data_model_get_n_rows (model);
-		if (nrows >= 1) {
+		if (0 && nrows >= 1) {
 			GdaDataModel *pkmodel;
 			sql = "SELECT column_name FROM _key_column_usage WHERE constraint_catalog = ##cc::string AND constraint_schema = ##cs::string AND constraint_name = ##cname::string ORDER BY ordinal_position";
 			pkmodel = gda_meta_store_extract (store, sql, error, 
 							  "cc", gda_data_model_get_value_at (model, 0, 0),
 							  "cs", gda_data_model_get_value_at (model, 1, 0),
-							  "cname", gda_data_model_get_value_at (model, 2, 0), NULL);
+							  "cname", gda_data_model_get_value_at (model, 0, 0), NULL);
 			if (!pkmodel) {
 				g_object_unref (model);
 				goto onerror;
@@ -488,45 +528,47 @@
 		g_object_unref (model);
 
 		/* foreign keys */
-		sql = "SELECT t.table_catalog, t.table_schema, t.table_name FROM _tables as f INNER JOIN _table_constraints as tc ON (tc.table_catalog=f.table_catalog AND tc.table_schema=f.table_schema AND tc.table_name=f.table_name) INNER JOIN _referential_constraints as rc ON (rc.constraint_catalog = tc.constraint_catalog AND rc.constraint_schema=tc.constraint_schema AND rc.constraint_name=tc.constraint_name) INNER JOIN _table_constraints as tc2 ON (rc.unique_constraint_catalog = tc2.constraint_catalog AND rc.unique_constraint_schema=tc2.constraint_schema AND rc.unique_constraint_name=tc2.constraint_name) INNER JOIN _tables as t ON (tc2.table_catalog=t.table_catalog AND tc2.table_schema=t.table_schema AND tc2.table_name=t.table_name) WHERE f.table_catalog = ##tc::string AND f.table_schema = ##ts::string AND f.table_name = ##tname::string";
-		model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
-		if (!model) 
-			goto onerror;
-
-		nrows = gda_data_model_get_n_rows (model);
-		for (i = 0; i < nrows; i++) {
-			GdaMetaTableForeignKey *tfk;
-			const GValue *fk_catalog, *fk_schema, *fk_name;
-
-			fk_catalog = gda_data_model_get_value_at (model, 0, i);
-			fk_schema = gda_data_model_get_value_at (model, 1, i);
-			fk_name = gda_data_model_get_value_at (model, 2, i);
-			tfk = g_new0 (GdaMetaTableForeignKey, 1);
-			tfk->meta_table = dbo;
-			tfk->depend_on = gda_meta_struct_get_db_object (mstruct, fk_catalog, fk_schema, fk_name);
-			if (!tfk->depend_on) {
-				gchar *str;
-				tfk->depend_on = g_new0 (GdaMetaDbObject, 1);
-				tfk->depend_on->obj_type = GDA_META_DB_UNKNOWN;
-				tfk->depend_on->obj_catalog = g_strdup (g_value_get_string (fk_catalog));
-				tfk->depend_on->obj_schema = g_strdup (g_value_get_string (fk_schema));
-				tfk->depend_on->obj_name = g_strdup (g_value_get_string (fk_name));
-				mstruct->db_objects = g_slist_append (mstruct->db_objects, tfk->depend_on);
-				str = g_strdup_printf ("%s.%s.%s", g_value_get_string (fk_catalog), 
-						       g_value_get_string (fk_schema), 
-						       g_value_get_string (fk_name));
-				g_hash_table_insert (mstruct->priv->index, str, tfk->depend_on);
+		if (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS) { 
+			sql = "SELECT ref_table_catalog, ref_table_schema, ref_table_name FROM _referential_constraints WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
+			model = gda_meta_store_extract (store, sql, error, "tc", catalog, "ts", schema, "tname", name, NULL);
+			if (!model) 
+				goto onerror;
+			
+			nrows = gda_data_model_get_n_rows (model);
+			for (i = 0; i < nrows; i++) {
+				GdaMetaTableForeignKey *tfk;
+				const GValue *fk_catalog, *fk_schema, *fk_name;
+				
+				fk_catalog = gda_data_model_get_value_at (model, 0, i);
+				fk_schema = gda_data_model_get_value_at (model, 1, i);
+				fk_name = gda_data_model_get_value_at (model, 2, i);
+				tfk = g_new0 (GdaMetaTableForeignKey, 1);
+				tfk->meta_table = dbo;
+				tfk->depend_on = gda_meta_struct_get_db_object (mstruct, fk_catalog, fk_schema, fk_name);
+				if (!tfk->depend_on) {
+					gchar *str;
+					tfk->depend_on = g_new0 (GdaMetaDbObject, 1);
+					tfk->depend_on->obj_type = GDA_META_DB_UNKNOWN;
+					tfk->depend_on->obj_catalog = g_strdup (g_value_get_string (fk_catalog));
+					tfk->depend_on->obj_schema = g_strdup (g_value_get_string (fk_schema));
+					tfk->depend_on->obj_name = g_strdup (g_value_get_string (fk_name));
+					mstruct->db_objects = g_slist_append (mstruct->db_objects, tfk->depend_on);
+					str = g_strdup_printf ("%s.%s.%s", g_value_get_string (fk_catalog), 
+							       g_value_get_string (fk_schema), 
+							       g_value_get_string (fk_name));
+					g_hash_table_insert (mstruct->priv->index, str, tfk->depend_on);
+				}
+				dbo->depend_list = g_slist_append (dbo->depend_list, tfk->depend_on);
+				
+				/* FIXME: compute @cols_nb, and all the @*_array members (ref_pk_cols_array must be
+				 * initialized with -1 values everywhere */
+				
+				mt->fk_list = g_slist_prepend (mt->fk_list, tfk);
 			}
-			dbo->depend_list = g_slist_append (dbo->depend_list, tfk->depend_on);
-
-			/* FIXME: compute @cols_nb, and all the @*_array members (ref_pk_cols_array must be
-			 * initialized with -1 values everywhere */
-
-			mt->fk_list = g_slist_prepend (mt->fk_list, tfk);
+			mt->fk_list = g_slist_reverse (mt->fk_list);
+			g_object_unref (model);
+			/* Note: mt->reverse_fk_list is not determined here */
 		}
-		mt->fk_list = g_slist_reverse (mt->fk_list);
-		g_object_unref (model);
-		/* Note: mt->reverse_fk_list is not determined here */
 		
 		break;
 	}
@@ -542,7 +584,7 @@
 				       g_value_get_string (name));
 		g_hash_table_insert (mstruct->priv->index, str, dbo);
 	}
-	if (dbo) {
+	if (dbo && (mstruct->priv->features & GDA_META_STRUCT_FEATURE_FOREIGN_KEYS)) {
 		/* compute GdaMetaTableForeignKey's @ref_pk_cols_array arrays and GdaMetaTable' @reverse_fk_list lists*/
 		GSList *list;
 		for (list = mstruct->db_objects; list; list = list->next) {
@@ -666,6 +708,8 @@
 	GSList *pass_list;
 	GSList *ordered_list = NULL;
 
+	g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), FALSE);
+
 	switch (sort_type) {
 	case GDA_META_SORT_ALHAPETICAL:
 		mstruct->db_objects = g_slist_sort (mstruct->db_objects, (GCompareFunc) db_object_sort_func);
@@ -696,13 +740,16 @@
 /**
  * gda_meta_struct_get_db_object
  * @mstruct: a #GdaMetaStruct object
- * @catalog: the catalog the object belongs to (as a G_TYPE_STRING GValue)
- * @schema: the schema the object belongs to (as a G_TYPE_STRING GValue)
- * @name: the object's name (as a G_TYPE_STRING GValue)
+ * @catalog: the catalog the object belongs to (as a G_TYPE_STRING GValue), or %NULL
+ * @schema: the schema the object belongs to (as a G_TYPE_STRING GValue), or %NULL
+ * @name: the object's name (as a G_TYPE_STRING GValue), not %NULL
  *
  * Tries to locate the #GdaMetaDbObject structure representing the database object named after
  * @catalog, @schema and @name.
  *
+ * If one or both of @catalog and @schema are %NULL, and more than one database object matches the name, then
+ * the return value is also %NULL.
+ *
  * Returns: the #GdaMetaDbObject or %NULL if not found
  */
 GdaMetaDbObject *
@@ -711,16 +758,55 @@
 	gchar *key;
 	GdaMetaDbObject *dbo;
 
-	g_return_val_if_fail (mstruct, NULL);
-	g_return_val_if_fail (catalog && (G_VALUE_TYPE (catalog) == G_TYPE_STRING), NULL);
-	g_return_val_if_fail (schema && (G_VALUE_TYPE (schema) == G_TYPE_STRING), NULL);
+	g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
 	g_return_val_if_fail (name && (G_VALUE_TYPE (name) == G_TYPE_STRING), NULL);
 
-	key = g_strdup_printf ("%s.%s.%s", g_value_get_string (catalog), g_value_get_string (schema), 
-			       g_value_get_string (name));
-	dbo = g_hash_table_lookup (mstruct->priv->index, key);
-	g_free (key);
-	return dbo;
+	if (catalog && schema) {
+		g_return_val_if_fail (G_VALUE_TYPE (catalog) == G_TYPE_STRING, NULL);
+		g_return_val_if_fail (G_VALUE_TYPE (schema) == G_TYPE_STRING, NULL);
+
+		key = g_strdup_printf ("%s.%s.%s", g_value_get_string (catalog), g_value_get_string (schema), 
+				       g_value_get_string (name));
+		dbo = g_hash_table_lookup (mstruct->priv->index, key);
+		g_free (key);
+		return dbo;
+	}
+	else {
+		/* walk through all the objects, and pick the ones with a matching name */
+		GSList *list;
+		GSList *matching = NULL;
+		const gchar *obj_name = g_value_get_string (name);
+		const gchar *obj_schema = NULL, *obj_catalog = NULL;
+		if (catalog) {
+			g_return_val_if_fail (G_VALUE_TYPE (catalog) == G_TYPE_STRING, NULL);
+			obj_catalog = g_value_get_string (catalog);
+		}
+		if (schema) {
+			g_return_val_if_fail (G_VALUE_TYPE (schema) == G_TYPE_STRING, NULL);
+			obj_schema = g_value_get_string (schema);
+		}
+
+		for (list = mstruct->db_objects; list; list = list->next) {
+			GdaMetaDbObject *dbo;
+			dbo = GDA_META_DB_OBJECT (list->data);
+			if (!strcmp (dbo->obj_name, obj_name) &&
+			    (!obj_schema || !strcmp (dbo->obj_schema, obj_schema)) &&
+			    (!obj_catalog || !strcmp (dbo->obj_catalog, obj_catalog)))
+				matching = g_slist_prepend (matching, dbo);
+		}
+
+		if (matching && !matching->next) {
+			GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (matching->data);
+			g_slist_free (matching);
+			return dbo;
+		}
+		else {
+			/* none or more than one found => return NULL */
+			if (matching)
+				g_slist_free (matching);
+			return NULL;
+		}
+	}
 }
 
 /**
@@ -738,7 +824,7 @@
 {
 	GSList *list;
 	const gchar *cname;
-	g_return_val_if_fail (mstruct, NULL);
+	g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
 	g_return_val_if_fail (table, NULL);
 	g_return_val_if_fail (col_name && (G_VALUE_TYPE (col_name) == G_TYPE_STRING), NULL);
 	cname = g_value_get_string (col_name);
@@ -752,23 +838,135 @@
 }
 
 /**
- * gda_meta_struct_free
+ * gda_meta_struct_dump_as_graph
  * @mstruct: a #GdaMetaStruct object
- * 
- * Releases any memory associated to @mstruct.
+ * @info: informs what kind of information to show in the resulting graph
+ * @error: a place to store errors, or %NULL
+ *
+ * Creates a new graph (in the GraphViz syntax) representation of @mstruct.
+ *
+ * Returns: a new string, or %NULL if an error occurred.
  */
-void
-gda_meta_struct_free (GdaMetaStruct *mstruct)
+gchar *
+gda_meta_struct_dump_as_graph (GdaMetaStruct *mstruct, GdaMetaGraphInfo info, GError **error)
 {
-	if (!mstruct)
-		return;
+	GString *string;
+	gchar *result;
 
-	g_slist_foreach (mstruct->db_objects, (GFunc) gda_meta_db_object_free, NULL);
-	g_slist_free (mstruct->db_objects);
-	g_hash_table_destroy (mstruct->priv->index);
-	g_free (mstruct);
-}
+	g_return_val_if_fail (GDA_IS_META_STRUCT (mstruct), NULL);
+	
+	string = g_string_new ("digraph G {\nrankdir = BT;\nnode [shape = plaintext];\n");
+	GSList *dbo_list;
+	for (dbo_list = mstruct->db_objects; dbo_list; dbo_list = dbo_list->next) {
+		gchar *objname, *fullname;
+		GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (dbo_list->data);
+		GSList *list;
+		gboolean use_html = (info & GDA_META_GRAPH_COLUMNS) ? TRUE : FALSE;
+
+		/* obj human readable name, and full name */
+		fullname = g_strdup_printf ("%s.%s.%s", dbo->obj_catalog, dbo->obj_schema, dbo->obj_name);
+		if (dbo->obj_short_name) 
+			objname = g_strdup (dbo->obj_short_name);
+		else
+			objname = g_strdup_printf ("%s.%s", dbo->obj_schema, dbo->obj_name);
+
+		/* node */
+		switch (dbo->obj_type) {
+		case GDA_META_DB_UNKNOWN:
+			break;
+		case GDA_META_DB_TABLE:
+			if (use_html) {
+				g_string_append_printf (string, "\"%s\" [label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname);
+				g_string_append_printf (string, "<TR><TD COLSPAN=\"2\" BGCOLOR=\"grey\" BORDER=\"1\">%s</TD></TR>", objname);
+			}
+			else
+				g_string_append_printf (string, "\"%s\" [ shape = box label = \"%s\" ]", fullname, objname);
+			break;
+		case GDA_META_DB_VIEW:
+			if (use_html) {
+				g_string_append_printf (string, "\"%s\" [label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname);
+				g_string_append_printf (string, "<TR><TD BGCOLOR=\"yellow\" BORDER=\"1\">%s</TD></TR>", objname);
+			}
+			else
+				g_string_append_printf (string, "\"%s\" [ shape = ellipse, label = \"%s\" ]", fullname, objname);
+			break;
+		default:
+			TO_IMPLEMENT;
+			g_string_append_printf (string, "\"%s\" [ shape = note label = \"%s\" ]", fullname, objname);
+			break;
+		}
+
+		/* columns, only for tables */
+		if (dbo->obj_type == GDA_META_DB_TABLE) {
+			GdaMetaTable *mt = GDA_META_DB_OBJECT_GET_TABLE (dbo);
+			GSList *depend_dbo_list = NULL;
+			if (info & GDA_META_GRAPH_COLUMNS) {
+				for (list = mt->columns; list; list = list->next) {
+					GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
+					GString *extra = g_string_new ("");
+					if (tcol->pkey)
+						g_string_append_printf (extra, "key");
+					g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD><TD ALIGN=\"right\">%s</TD></TR>", 
+								tcol->column_name, extra->str);
+					g_string_free (extra, TRUE);
+				}
+			}
+			if (use_html)
+				g_string_append (string, "</TABLE>>];\n");
+			/* foreign keys */
+			for (list = mt->fk_list; list; list = list->next) {
+				GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (list->data);
+				if (tfk->depend_on->obj_type != GDA_META_DB_UNKNOWN) {
+					g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", fullname,
+								tfk->depend_on->obj_catalog, tfk->depend_on->obj_schema, 
+								tfk->depend_on->obj_name);
+					depend_dbo_list = g_slist_prepend (depend_dbo_list, tfk->depend_on);
+				}
+			}
+
+			/* dependencies other than foreign keys */
+			for (list = dbo->depend_list; list; list = list->next) {
+				if (!g_slist_find (depend_dbo_list, list->data)) {
+					GdaMetaDbObject *dep_dbo = GDA_META_DB_OBJECT (list->data);
+					if (dep_dbo->obj_type != GDA_META_DB_UNKNOWN) 
+						g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", 
+									fullname,
+									dep_dbo->obj_catalog, dep_dbo->obj_schema, 
+									dep_dbo->obj_name);
+				}
+			}
+
+			g_slist_free (depend_dbo_list);
+		}
+		else if (dbo->obj_type == GDA_META_DB_VIEW) {
+			GdaMetaTable *mt = GDA_META_DB_OBJECT_GET_TABLE (dbo);
+			if (info & GDA_META_GRAPH_COLUMNS) {
+				for (list = mt->columns; list; list = list->next) {
+					GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
+					g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD></TR>", tcol->column_name);
+				}
+			}
+			if (use_html)
+				g_string_append (string, "</TABLE>>];\n");
+			/* dependencies */
+			for (list = dbo->depend_list; list; list = list->next) {
+				GdaMetaDbObject *ddbo = GDA_META_DB_OBJECT (list->data);
+				if (ddbo->obj_type != GDA_META_DB_UNKNOWN) 
+					g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\";\n", fullname,
+								ddbo->obj_catalog, ddbo->obj_schema, 
+								ddbo->obj_name);
+			}
+		}
 
+		g_free (objname);
+		g_free (fullname);
+	}
+	g_string_append_c (string, '}');
+
+	result = string->str;
+	g_string_free (string, FALSE);
+	return result;
+}
 
 static void
 gda_meta_db_object_free (GdaMetaDbObject *dbo)
@@ -838,7 +1036,7 @@
 
 static gboolean 
 determine_db_object_from_schema_and_name (GdaMetaStruct *mstruct, GdaMetaStore *store, 
-					  GdaMetaDbObjectType type, GValue **out_catalog,
+					  GdaMetaDbObjectType *in_out_type, GValue **out_catalog,
 					  GValue **out_short_name, 
 					  GValue **out_full_name, GValue **out_owner, 
 					  const GValue *schema, const GValue *name)
@@ -848,9 +1046,26 @@
 	*out_full_name = NULL;
 	*out_owner = NULL;
 
-	switch (type) {
-	case GDA_META_DB_UNKNOWN:
+	switch (*in_out_type) {
+	case GDA_META_DB_UNKNOWN: {
+		GdaMetaDbObjectType type = GDA_META_DB_TABLE;
+		if (determine_db_object_from_schema_and_name (mstruct, store, &type, out_catalog,
+							      out_short_name, out_full_name, out_owner,
+							      schema, name)) {
+			*in_out_type = GDA_META_DB_TABLE;
+			return TRUE;
+		}
+		type = GDA_META_DB_VIEW;
+		if (determine_db_object_from_schema_and_name (mstruct, store, &type, out_catalog,
+							      out_short_name, out_full_name, out_owner,
+							      schema, name)) {
+			*in_out_type = GDA_META_DB_VIEW;
+			return TRUE;
+		}
+		return FALSE;
 		break;
+	}
+
 	case GDA_META_DB_TABLE: {
 		const gchar *sql = "SELECT table_catalog, table_short_name, table_full_name, table_owner FROM _tables as t WHERE table_schema = ##ts::string AND table_short_name = ##tname::string AND table_name NOT IN (SELECT v.table_name FROM _views as v WHERE v.table_catalog=t.table_catalog AND v.table_schema=t.table_schema)";
 		GdaDataModel *model;
@@ -871,6 +1086,7 @@
 		g_object_unref (model);
 		return TRUE;
 	}
+
 	case GDA_META_DB_VIEW:{
 		const gchar *sql = "SELECT table_catalog, table_short_name, table_full_name, table_owner FROM _tables NATURAL JOIN _views WHERE table_schema = ##ts::string AND table_short_name = ##tname::string";
 		GdaDataModel *model;
@@ -900,7 +1116,7 @@
 
 static gboolean
 determine_db_object_from_short_name (GdaMetaStruct *mstruct, GdaMetaStore *store, 
-				     GdaMetaDbObjectType type, GValue **out_catalog,
+				     GdaMetaDbObjectType *in_out_type, GValue **out_catalog,
 				     GValue **out_schema, GValue **out_name, GValue **out_short_name, 
 				     GValue **out_full_name, GValue **out_owner, const GValue *name)
 {
@@ -912,9 +1128,24 @@
 	*out_owner = NULL;
 
 	/* general lookup */
-	switch (type) {
-	case GDA_META_DB_UNKNOWN:
+	switch (*in_out_type) {
+	case GDA_META_DB_UNKNOWN: {
+		GdaMetaDbObjectType type = GDA_META_DB_TABLE;
+		if (determine_db_object_from_short_name (mstruct, store, &type, out_catalog, out_schema, out_name,
+							 out_short_name, out_full_name, out_owner, name)) {
+			*in_out_type = GDA_META_DB_TABLE;
+			return TRUE;
+		}
+		type = GDA_META_DB_VIEW;
+		if (determine_db_object_from_short_name (mstruct, store, &type, out_catalog, out_schema, out_name,
+							 out_short_name, out_full_name, out_owner, name)) {
+			*in_out_type = GDA_META_DB_VIEW;
+			return TRUE;
+		}
+		return FALSE;
 		break;
+	}
+
 	case GDA_META_DB_TABLE: {
 		const gchar *sql = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner FROM _tables as t WHERE table_short_name = ##tname::string AND table_name NOT IN (SELECT v.table_name FROM _views as v WHERE v.table_catalog=t.table_catalog AND v.table_schema=t.table_schema)";
 		GdaDataModel *model;
@@ -937,6 +1168,7 @@
 		g_object_unref (model);
 		return TRUE;
 	}
+
 	case GDA_META_DB_VIEW:{
 		const gchar *sql = "SELECT table_catalog, table_schema, table_name, table_short_name, table_full_name, table_owner FROM _tables NATURAL JOIN _views WHERE table_short_name = ##tname::string";
 		GdaDataModel *model;
@@ -978,7 +1210,7 @@
 			*ptr = 0;
 			g_value_set_string ((sv = gda_value_new (G_TYPE_STRING)), tmp);
 			g_value_set_string ((nv = gda_value_new (G_TYPE_STRING)), ptr + 1);
-			retval = determine_db_object_from_schema_and_name (mstruct, store, type, out_catalog, 
+			retval = determine_db_object_from_schema_and_name (mstruct, store, in_out_type, out_catalog, 
 									   out_short_name, out_full_name, out_owner, 
 									   sv, nv);
 			if (retval) {
@@ -996,3 +1228,40 @@
 
 	return FALSE;
 }
+
+static gboolean
+determine_db_object_from_missing_type (GdaMetaStruct *mstruct, GdaMetaStore *store, 
+				       GdaMetaDbObjectType *out_type, GValue **out_short_name, 
+				       GValue **out_full_name, GValue **out_owner, const GValue *catalog, 
+				       const GValue *schema, const GValue *name)
+{
+	/* try as a view first */
+	const gchar *sql = "SELECT table_short_name, table_full_name, table_owner FROM _tables NATURAL JOIN _views WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
+	GdaDataModel *model;
+
+	model = gda_meta_store_extract (store, sql, NULL, "tc", catalog, "ts", schema, "tname", name, NULL);
+	if (model && (gda_data_model_get_n_rows (model) == 1)) {
+		*out_type = GDA_META_DB_VIEW;
+		*out_short_name = gda_value_copy (gda_data_model_get_value_at (model, 0, 0));
+		*out_full_name = gda_value_copy (gda_data_model_get_value_at (model, 1, 0));
+		*out_owner = gda_value_copy (gda_data_model_get_value_at (model, 2, 0));
+		g_object_unref (model);
+		return TRUE;
+	}
+	if (model) g_object_unref (model);
+
+	/* try as a table */
+	sql = "SELECT table_short_name, table_full_name, table_owner FROM _tables WHERE table_catalog = ##tc::string AND table_schema = ##ts::string AND table_name = ##tname::string";
+	model = gda_meta_store_extract (store, sql, NULL, "tc", catalog, "ts", schema, "tname", name, NULL);
+	if (model && (gda_data_model_get_n_rows (model) == 1)) {
+		*out_type = GDA_META_DB_TABLE;
+		*out_short_name = gda_value_copy (gda_data_model_get_value_at (model, 0, 0));
+		*out_full_name = gda_value_copy (gda_data_model_get_value_at (model, 1, 0));
+		*out_owner = gda_value_copy (gda_data_model_get_value_at (model, 2, 0));
+		g_object_unref (model);
+		return TRUE;
+	}
+	if (model) g_object_unref (model);
+	
+	return FALSE;
+}

Modified: trunk/libgda/gda-meta-struct.h
==============================================================================
--- trunk/libgda/gda-meta-struct.h	(original)
+++ trunk/libgda/gda-meta-struct.h	Wed Mar 12 21:18:24 2008
@@ -24,6 +24,7 @@
 #include <glib-object.h>
 #include <libgda/gda-data-model.h>
 #include <libgda/gda-meta-store.h>
+#include <libgda/gda-decl.h>
 
 G_BEGIN_DECLS
 
@@ -32,10 +33,6 @@
 #define GDA_META_STRUCT_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, gda_meta_struct_get_type (), GdaMetaStructClass)
 #define GDA_IS_META_STRUCT(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, gda_meta_struct_get_type ())
 
-typedef struct _GdaMetaStruct        GdaMetaStruct;
-typedef struct _GdaMetaStructClass   GdaMetaStructClass;
-typedef struct _GdaMetaStructPrivate GdaMetaStructPrivate;
-
 /* error reporting */
 extern GQuark gda_meta_struct_error_quark (void);
 #define GDA_META_STRUCT_ERROR gda_meta_struct_error_quark ()
@@ -74,9 +71,12 @@
  * Controls which features are computed about database objects
  */
 typedef enum {
-	GDA_META_STRUCT_FEATURE_ALL,
-	GDA_META_STRUCT_FEATURE_FOREIGN_KEYS,
-	GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES
+	GDA_META_STRUCT_FEATURE_NONE              = 0,
+	GDA_META_STRUCT_FEATURE_FOREIGN_KEYS      = 1 << 0,
+	GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES = 1 << 1,
+
+	GDA_META_STRUCT_FEATURE_ALL               = GDA_META_STRUCT_FEATURE_FOREIGN_KEYS |
+	                                            GDA_META_STRUCT_FEATURE_VIEW_DEPENDENCIES
 } GdaMetaStructFeature;
 
 /*
@@ -103,7 +103,7 @@
 	GSList       *fk_list; /* list of GdaMetaTableForeignKey where @gda_meta_table == this GdaMetaDbObject */
 } GdaMetaTable;
 
-/*
+/**
  * Complements the GdaMetaDbObject structure, for views only
  * contains more information than for tables
  */
@@ -113,7 +113,7 @@
 	gboolean      is_updatable;
 } GdaMetaView;
 
-/* 
+/*
  * Struture to hold information about each object
  * which can be created in the internal GdaMetaStore's connection.
  * It is available for tables, views, triggers, ...
@@ -162,7 +162,7 @@
 
 
 GType               gda_meta_struct_get_type         (void) G_GNUC_CONST;
-GdaMetaStruct      *gda_meta_struct_new              (void);
+GdaMetaStruct      *gda_meta_struct_new              (GdaMetaStructFeature features);
 GdaMetaDbObject    *gda_meta_struct_complement       (GdaMetaStruct *mstruct, GdaMetaStore *store, GdaMetaDbObjectType type,
                                                       const GValue *catalog, const GValue *schema, const GValue *name,
                                                       GError **error);
@@ -172,6 +172,12 @@
 GdaMetaTableColumn *gda_meta_struct_get_table_column (GdaMetaStruct *mstruct, GdaMetaTable *table,
                                                       const GValue *col_name);
 
+typedef enum {
+	GDA_META_GRAPH_COLUMNS = 1 << 0
+} GdaMetaGraphInfo;
+
+gchar              *gda_meta_struct_dump_as_graph    (GdaMetaStruct *mstruct, GdaMetaGraphInfo info, GError **error);
+
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/gda-server-operation.c
==============================================================================
--- trunk/libgda/gda-server-operation.c	(original)
+++ trunk/libgda/gda-server-operation.c	Wed Mar 12 21:18:24 2008
@@ -1953,8 +1953,11 @@
 				param = gda_set_get_holder (opnode->d.plist, extension);
 				if (param) {
 					GValue *v;
-					v = gda_value_new_from_string (value, 
-								       gda_holder_get_g_type (param));
+					if (value)
+						v = gda_value_new_from_string (value, 
+									       gda_holder_get_g_type (param));
+					else
+						v = gda_value_new_null ();
 					if (!gda_holder_take_value (param, v)) {
 						g_set_error (error, 0, 0,
 							     _("Could not set parameter '%s' to value '%s'"), 
@@ -1995,8 +1998,11 @@
 						
 						if (allok) {
 							GValue *gvalue;
-							gvalue = gda_value_new_from_string (value, 
-											    gda_column_get_g_type (column));
+							if (value)
+								gvalue = gda_value_new_from_string (value, 
+												    gda_column_get_g_type (column));
+							else
+								gvalue = gda_value_new_null ();
 							allok = gda_data_model_set_value_at (opnode->d.model,
 											     gda_column_get_position (column), 
 											     row, gvalue, error);
@@ -2009,8 +2015,11 @@
 		}
 		case GDA_SERVER_OPERATION_NODE_PARAM: {
 			GValue *v;
-			v = gda_value_new_from_string (value, 
-						       gda_holder_get_g_type (opnode->d.param));
+			if (value)
+				v = gda_value_new_from_string (value, 
+							       gda_holder_get_g_type (opnode->d.param));
+			else
+				v = gda_value_new_null ();
 			if (!gda_holder_take_value (opnode->d.param, v)) {
 				g_set_error (error, 0, 0,
 					     _("Could not set parameter '%s' to value '%s'"), 

Modified: trunk/libgda/gda-server-provider.h
==============================================================================
--- trunk/libgda/gda-server-provider.h	(original)
+++ trunk/libgda/gda-server-provider.h	Wed Mar 12 21:18:24 2008
@@ -63,24 +63,39 @@
 };
 
 typedef struct {
-	gboolean (*info)          (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-	gboolean (*btypes)        (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-	gboolean (*schemata)      (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-				   const GValue *schema_name);
-	gboolean (*tables_views)  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-	gboolean (*tables_views_s)(GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-				   const GValue *table_schema, const GValue *table_name);
-	gboolean (*columns)       (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-	gboolean (*columns_t)     (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-				   const GValue *table_schema, const GValue *table_name);
-	gboolean (*columns_c)     (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-				   const GValue *table_schema, const GValue *table_name, const GValue *column_name);
-	gboolean (*constraints_tab)(GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-	gboolean (*constraints_tab_s)(GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-				      const GValue *table_schema, const GValue *table_name);
-	gboolean (*constraints_ref)(GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-	gboolean (*constraints_ref_c)(GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-				      const GValue *constraint_schema, const GValue *constraint_name);
+	/* _information_schema_catalog_name */
+	gboolean (*_info)            (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+
+	/* _builtin_data_types */
+	gboolean (*_btypes)          (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+
+
+	/* _schemata */
+	gboolean (*_schemata)        (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+	gboolean (*schemata)         (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
+				      const GValue *catalog_name, const GValue *schema_name_n);
+
+	/* _tables or _views */
+	gboolean (*_tables_views)    (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+	gboolean (*tables_views)     (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+				      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n);
+
+	/* _columns */
+	gboolean (*_columns)         (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+	gboolean (*columns)          (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+				      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name);
+
+	/* _table_constraints */
+	gboolean (*_constraints_tab) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+	gboolean (*constraints_tab)  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
+				      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+				      const GValue *constraint_name_n);
+
+	/* _referential_constraints */
+	gboolean (*_constraints_ref) (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
+	gboolean (*constraints_ref)  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+				      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+				      const GValue *constraint_name);
 } GdaServerProviderMeta;
 
 typedef void (*GdaServerProviderAsyncCallback) (GdaServerProvider *provider, GdaConnection *cnc, guint task_id, 

Modified: trunk/libgda/gda-value.c
==============================================================================
--- trunk/libgda/gda-value.c	(original)
+++ trunk/libgda/gda-value.c	Wed Mar 12 21:18:24 2008
@@ -1798,7 +1798,7 @@
 	g_return_val_if_fail (value1 && value2, -1);
 	g_return_val_if_fail (G_VALUE_TYPE (value1) == G_VALUE_TYPE (value2), -1);
 
-	type = G_VALUE_TYPE(value1);
+	type = G_VALUE_TYPE (value1);
 	
 	if (value1 == value2)
 		return 0;
@@ -1868,10 +1868,19 @@
 			return (v1 > v2) ? 1 : -1;
 	}
 
-	else if (type == GDA_TYPE_GEOMETRIC_POINT)
-		return memcmp (gda_value_get_geometric_point(value1) , 
-			       gda_value_get_geometric_point(value2),
-			       sizeof (GdaGeometricPoint));
+	else if (type == GDA_TYPE_GEOMETRIC_POINT) {
+		const GdaGeometricPoint *p1, *p2;
+		p1 = gda_value_get_geometric_point (value1);
+		p2 = gda_value_get_geometric_point (value2);
+		if (p1 && p2)
+			return memcmp (p1, p2, sizeof (GdaGeometricPoint));
+		else if (p1)
+			return 1;
+		else if (p2)
+			return -1;
+		else
+			return 0;
+	}
 
 	else if (type == G_TYPE_OBJECT) {
 		if (g_value_get_object (value1) == g_value_get_object (value2))
@@ -1958,15 +1967,34 @@
 		return retval;
 	}
 	
-	else if (type == GDA_TYPE_TIME)
-		return memcmp (gda_value_get_time(value1), gda_value_get_time(value2),
-			       sizeof (GdaTime));
-
-	else if (type == GDA_TYPE_TIMESTAMP)
-		return memcmp (gda_value_get_timestamp(value1), 
-			       gda_value_get_timestamp(value2),
-			       sizeof (GdaTimestamp));
-	
+	else if (type == GDA_TYPE_TIME) {
+		const GdaTime *t1, *t2;
+		t1 = gda_value_get_time (value1);
+		t2 = gda_value_get_time (value2);
+		if (t1 && t2)
+			return memcmp (t1, t2, sizeof (GdaTime));
+		else if (t1)
+			return 1;
+		else if (t2)
+			return -1;
+		else
+			return 0;
+	}
+
+	else if (type == GDA_TYPE_TIMESTAMP) {
+		const GdaTimestamp *ts1, *ts2;
+		ts1 = gda_value_get_timestamp (value1);
+		ts2 = gda_value_get_timestamp (value2);
+		if (ts1 && ts2)
+			return memcmp (ts1, ts2, sizeof (GdaTimestamp));
+		else if (ts1)
+			return 1;
+		else if (ts2)
+			return -1;
+		else
+			return 0;
+	}
+
 	else if (type == G_TYPE_CHAR)
 		return (g_value_get_char (value1) > g_value_get_char (value2)) ? 1 : 
 			((g_value_get_char (value1) == g_value_get_char (value2)) ? 0 : -1);

Modified: trunk/libgda/information_schema.xml
==============================================================================
--- trunk/libgda/information_schema.xml	(original)
+++ trunk/libgda/information_schema.xml	Wed Mar 12 21:18:24 2008
@@ -69,6 +69,10 @@
     <column name="udt_full_name"/>
     <column name="udt_internal" type="boolean"/>
     <column name="udt_owner" nullok="TRUE"/>
+    <fkey ref_table="_schemata">
+      <part column="udt_catalog" ref_column="catalog_name"/>
+      <part column="udt_schema" ref_column="schema_name"/>
+    </fkey>
     <unique>
       <column name="udt_full_name"/>
     </unique>
@@ -330,14 +334,15 @@
   </table>
 
   <table name="_table_constraints">
-    <column name="constraint_catalog" pkey="TRUE"/>
-    <column name="constraint_schema" pkey="TRUE"/>
+    <column name="constraint_catalog" nullok="TRUE" descr="Name of the catalog that contains the constraint"/>
+    <column name="constraint_schema" nullok="TRUE" descr="Name of the schema that contains the constraint"/>
+
     <column name="constraint_name" pkey="TRUE"/>
-    <column name="table_catalog"/>
-    <column name="table_schema"/>
-    <column name="table_name"/>
+    <column name="table_catalog" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE"/>
+    <column name="table_name" pkey="TRUE"/>
     <column name="constraint_type" descr="CHECK, FOREIGN KEY, PRIMARY KEY or UNIQUE"/>
-    <column name="check_clause" nullok="TRUE"/>
+    <column name="check_clause" nullok="TRUE" descr="The check expression if the constraint is a check constraint, NULL otherwise"/>
     <column name="is_deferrable" type="boolean" nullok="TRUE"/>
     <column name="initially_deferred" type="boolean" nullok="TRUE"/>
     <fkey ref_table="_tables">
@@ -345,46 +350,48 @@
       <part column="table_schema"/>
       <part column="table_name"/>
     </fkey>
-    <fkey ref_table="_schemata">
-      <part column="constraint_catalog" ref_column="catalog_name"/>
-      <part column="constraint_schema"  ref_column="schema_name"/>
-    </fkey>
   </table>
 
   <table name="_referential_constraints">
-    <column name="constraint_catalog" pkey="TRUE"/>
-    <column name="constraint_schema" pkey="TRUE"/>
+    <column name="table_catalog" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE"/>
+    <column name="table_name" pkey="TRUE"/>
     <column name="constraint_name" pkey="TRUE"/>
-    <column name="unique_constraint_catalog"/>
-    <column name="unique_constraint_schema"/>
-    <column name="unique_constraint_name"/>
+
+    <column name="ref_table_catalog"/>
+    <column name="ref_table_schema"/>
+    <column name="ref_table_name"/>
+    <column name="ref_constraint_name"/>
+
     <column name="match_option" nullok="TRUE"/>
     <column name="update_rule" nullok="TRUE"/>
     <column name="delete_rule" nullok="TRUE"/>
     <fkey ref_table="_table_constraints">
-      <part column="constraint_catalog"/>
-      <part column="constraint_schema"/>
+      <part column="table_catalog"/>
+      <part column="table_schema"/>
+      <part column="table_name"/>
       <part column="constraint_name"/>
     </fkey>
     <fkey ref_table="_table_constraints">
-      <part column="unique_constraint_catalog" ref_column="constraint_catalog"/>
-      <part column="unique_constraint_schema" ref_column="constraint_schema"/>
-      <part column="unique_constraint_name" ref_column="constraint_name"/>
+      <part column="ref_table_catalog" ref_column="table_catalog"/>
+      <part column="ref_table_schema" ref_column="table_schema"/>
+      <part column="ref_table_name" ref_column="table_name"/>
+      <part column="ref_constraint_name" ref_column="constraint_name"/>
     </fkey>
   </table>
 
   <table name="_key_column_usage">
-    <column name="constraint_catalog" pkey="TRUE"/>
-    <column name="constraint_schema" pkey="TRUE"/>
+    <column name="table_catalog" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE"/>
+    <column name="table_name" pkey="TRUE"/>
     <column name="constraint_name" pkey="TRUE"/>
-    <column name="table_catalog"/>
-    <column name="table_schema"/>
-    <column name="table_name"/>
-    <column name="column_name"/>
+    <column name="column_name" pkey="TRUE"/>
+
     <column name="ordinal_position" type="gint" pkey="TRUE"/>
     <fkey ref_table="_table_constraints">
-      <part column="constraint_catalog"/>
-      <part column="constraint_schema"/>
+      <part column="table_catalog"/>
+      <part column="table_schema"/>
+      <part column="table_name"/>
       <part column="constraint_name"/>
     </fkey>
     <fkey ref_table="_columns">
@@ -396,16 +403,15 @@
   </table>
 
   <table name="_check_column_usage">
-    <column name="constraint_catalog" pkey="TRUE"/>
-    <column name="constraint_schema" pkey="TRUE"/>
+    <column name="table_catalog" pkey="TRUE"/>
+    <column name="table_schema" pkey="TRUE"/>
+    <column name="table_name" pkey="TRUE"/>
     <column name="constraint_name" pkey="TRUE"/>
-    <column name="table_catalog"/>
-    <column name="table_schema"/>
-    <column name="table_name"/>
-    <column name="column_name"/>
+    <column name="column_name" pkey="TRUE"/>
     <fkey ref_table="_table_constraints">
-      <part column="constraint_catalog"/>
-      <part column="constraint_schema"/>
+      <part column="table_catalog"/>
+      <part column="table_schema"/>
+      <part column="table_name"/>
       <part column="constraint_name"/>
     </fkey>
     <fkey ref_table="_columns">
@@ -420,9 +426,6 @@
     <column name="view_catalog" pkey="TRUE"/>
     <column name="view_schema" pkey="TRUE"/>
     <column name="view_name" pkey="TRUE"/>
-    <column name="table_catalog" pkey="TRUE"/>
-    <column name="table_schema" pkey="TRUE"/>
-    <column name="table_name" pkey="TRUE"/>
     <column name="column_name" pkey="TRUE"/>
     <fkey ref_table="_views">
       <part column="view_catalog" ref_column="table_catalog"/>
@@ -430,20 +433,22 @@
       <part column="view_name" ref_column="table_name"/>
     </fkey>
     <fkey ref_table="_columns">
-      <part column="table_catalog"/>
-      <part column="table_schema"/>
-      <part column="table_name"/>
-      <part column="column_name"/>
+      <part column="view_catalog" ref_column="table_catalog"/>
+      <part column="view_schema" ref_column="table_schema"/>
+      <part column="view_name" ref_column="table_name"/>
+      <part column="column_name" ref_column="column_name"/>
     </fkey>
   </table>
 
   <table name="_domain_constraints">
-    <column name="constraint_catalog" pkey="TRUE"/>
-    <column name="constraint_schema" pkey="TRUE"/>
+    <column name="constraint_catalog" nullok="TRUE" descr="Name of the catalog that contains the constraint"/>
+    <column name="constraint_schema" nullok="TRUE" descr="Name of the schema that contains the constraint"/>
+
     <column name="constraint_name" pkey="TRUE"/>
-    <column name="domain_catalog"/>
-    <column name="domain_schema"/>
-    <column name="domain_name"/>
+    <column name="domain_catalog" pkey="TRUE"/>
+    <column name="domain_schema" pkey="TRUE"/>
+    <column name="domain_name" pkey="TRUE"/>
+
     <column name="check_clause" nullok="TRUE"/>
     <column name="is_deferrable" type="boolean" nullok="TRUE"/>
     <column name="initially_deferred" type="boolean" nullok="TRUE"/>
@@ -500,34 +505,5 @@
        domain_catalog, domain_schema, domain_name , NULL, NULL, NULL FROM _domains</definition>
   </view>
 
-  <view name="_constraint_column_usage">
-    <definition>SELECT table_catalog, table_schema, table_name, column_name, constraint_catalog, constraint_schema, constraint_name
-FROM _key_column_usage
-UNION
-SELECT table_catalog, table_schema, table_name, column_name, constraint_catalog, constraint_schema, constraint_name
-FROM _check_column_usage</definition>
-  </view>
-
-  <view name="_constraint_table_usage">
-    <definition>SELECT DISTINCT table_catalog, table_schema, table_name, constraint_catalog, constraint_schema, constraint_name
-FROM _constraint_column_usage</definition>
-  </view>
-
-  <view name="_view_table_usage">
-    <definition>SELECT DISTINCT view_catalog, view_schema, view_name, table_catalog, table_schema, table_name
-FROM _view_column_usage</definition>
-  </view>
-
-  <view name="_domain_column_usage">
-    <definition>SELECT d.domain_catalog, d.domain_schema, d.domain_name,
-       c.table_catalog, c.table_schema, c.table_name, c.column_name
-FROM _domains d INNER JOIN _columns c ON (c.data_type=d.domain_full_name)</definition>
-  </view>
-
-  <view name="_check_constraints">
-    <definition>SELECT constraint_catalog, constraint_schema, constraint_name, check_clause FROM _table_constraints
-      UNION
-      SELECT constraint_catalog, constraint_schema, constraint_name, check_clause FROM _domain_constraints</definition>
-  </view>
 
 </schema>

Modified: trunk/libgda/libgda-array.dtd
==============================================================================
--- trunk/libgda/libgda-array.dtd	(original)
+++ trunk/libgda/libgda-array.dtd	Wed Mar 12 21:18:24 2008
@@ -31,6 +31,7 @@
 
 <!ELEMENT gda_value (#PCDATA)>
 <!ATTLIST gda_value
+	  isnull NMTOKEN #IMPLIED
 	  xml:lang CDATA #IMPLIED>
 
 <!ELEMENT gda_array_value (#PCDATA)>

Modified: trunk/libgda/sqlite/gda-sqlite-meta.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-meta.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-meta.c	Wed Mar 12 21:18:24 2008
@@ -185,8 +185,8 @@
 
 gboolean 
 _gda_sqlite_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc, 
-			   GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-			   const GValue *schema_name)
+			   GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			   const GValue *catalog_name, const GValue *schema_name_n)
 {
 	GdaDataModel *model, *tmpmodel;
 	gboolean retval = TRUE;
@@ -204,8 +204,8 @@
 		const GValue *cvalue;
 		
 		cvalue = gda_data_model_get_value_at (tmpmodel, 1, i);
-		if (!schema_name || 
-		    !gda_value_compare_ext (schema_name, cvalue)) {
+		if (!schema_name_n || 
+		    !gda_value_compare_ext (schema_name_n, cvalue)) {
 			const gchar *cstr;
 			GValue *v1;
 
@@ -318,56 +318,10 @@
         return retval;
 }
 
-gboolean
-_gda_sqlite_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
-			       GdaMetaStore *store, GdaMetaContext *context, GError **error)
-{
-	GdaDataModel *tables_model, *views_model;
-	gboolean retval = TRUE;
-	tables_model = gda_meta_store_create_modify_data_model (store, "_tables");
-	g_assert (tables_model);
-	views_model = gda_meta_store_create_modify_data_model (store, "_views");
-	g_assert (views_model);
-	
-	GdaDataModel *sh_model;
-	sh_model = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_NAMESPACES, error, 0);
-	if (!sh_model)
-		retval = TRUE;
-	else {
-		gint nrows, i;
-		nrows = gda_data_model_get_n_rows (sh_model);
-		for (i = 0; i < nrows; i++) {
-			const GValue *p_table_schema = gda_data_model_get_value_at (sh_model, 0, i);
-			if (!fill_tables_views_model (cnc, tables_model, views_model, p_table_schema, NULL, error)) {
-				retval = FALSE;
-				break;
-			}
-		}
-		g_object_unref (sh_model);
-	}
-	
-	GdaMetaContext c2;
-	c2 = *context; /* copy contents, just because we need to modify @context->table_name */
-	if (retval) {
-		c2.table_name = "_tables";
-		retval = gda_meta_store_modify_with_context (store, &c2, tables_model, error);
-	}
-	if (retval) {
-		c2.table_name = "_views";
-		retval = gda_meta_store_modify_with_context (store, &c2, views_model, error);
-	}
-	g_object_unref (tables_model);
-	g_object_unref (views_model);
-
-	return retval;
-}
-
-
-
 gboolean 
-_gda_sqlite_meta_tables_views_s (GdaServerProvider *prov, GdaConnection *cnc, 
-				 GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-				 const GValue *table_schema, const GValue *table_name)
+_gda_sqlite_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+			       GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+			       const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n)
 {
 	GdaDataModel *tables_model, *views_model;
 	gboolean retval = TRUE;
@@ -376,7 +330,7 @@
 	views_model = gda_meta_store_create_modify_data_model (store, "_views");
 	g_assert (views_model);
 
-	if (! fill_tables_views_model (cnc, tables_model, views_model, table_schema, table_name, error))
+	if (! fill_tables_views_model (cnc, tables_model, views_model, table_schema, table_name_n, error))
 		retval = FALSE;
 
 	GdaMetaContext c2;
@@ -399,7 +353,7 @@
 fill_columns_model (GdaConnection *cnc, SqliteConnectionData *cdata, 
 		    GdaDataModel *mod_model, 
 		    const GValue *p_table_schema, const GValue *p_table_name,
-		    const GValue *p_column_name, GError **error)
+		    GError **error)
 {
 	GdaDataModel *tmpmodel;
 	gboolean retval = TRUE;
@@ -439,11 +393,6 @@
 		GType gtype = 0;
 		
 		this_col_pname = gda_data_model_get_value_at (tmpmodel, 1, i);
-		if (p_column_name &&
-		    gda_value_compare_ext (p_column_name, this_col_pname))
-			continue;
-
-		
 		this_table_name = g_value_get_string (p_table_name);
 		g_assert (this_table_name);
 		if (!strcmp (this_table_name, "sqlite_sequence"))
@@ -454,10 +403,12 @@
 						   this_table_name, this_col_name,
 						   &pzDataType, &pzCollSeq, &pNotNull, &pPrimaryKey, &pAutoinc)
 		    != SQLITE_OK) {
-			g_set_error (error, 0, 0,
-				     _("Internal error"));
-			retval = FALSE;
-			break;
+			/* may fail because we have a view and not a table => use @tmpmodel to fetch info. */
+			pzDataType = g_value_get_string (gda_data_model_get_value_at (tmpmodel, 2, i));
+			pzCollSeq = NULL;
+			pNotNull = g_value_get_int (gda_data_model_get_value_at (tmpmodel, 3, i));
+			pPrimaryKey = g_value_get_boolean (gda_data_model_get_value_at (tmpmodel, 5, i));
+			pAutoinc = 0;
 		}
 		
 		v1 = gda_value_copy (gda_data_model_get_value_at (tmpmodel, 0, i));
@@ -469,18 +420,24 @@
 		g_value_set_int (v1, g_value_get_int (v1) + 1);
 
 		
-		if (pzDataType)
-			gtype = GPOINTER_TO_INT (g_hash_table_lookup (cdata->types, pzDataType));
-		if (gtype == 0) {
-			g_warning ("Internal error: could not get GType for DBMS type '%s'", pzDataType);
-			g_value_set_string ((v6 = gda_value_new (G_TYPE_STRING)), "string");
+		if (pzDataType) {
+			gchar *tmp = g_strdup (pzDataType);
+			gchar *ptr;
+			for (ptr = tmp; *ptr && (*ptr != '(') && (*ptr != '['); ptr++);
+			if (*ptr)
+				*ptr = 0;
+			gtype = GPOINTER_TO_INT (g_hash_table_lookup (cdata->types, tmp));
+			g_free (tmp);
 		}
+		if (gtype == 0) 
+			/* default to string if nothing else */
+			g_value_set_string ((v6 = gda_value_new (G_TYPE_STRING)), "string");
 		else
 			g_value_set_string ((v6 = gda_value_new (G_TYPE_STRING)), g_type_name (gtype));
 		if (! append_a_row (mod_model, error, 25, 
-				    FALSE, catalog_value,
-				    FALSE, p_table_schema,
-				    FALSE, p_table_name,
+				    FALSE, catalog_value, /* table_catalog */
+				    FALSE, p_table_schema, /* table_schema */
+				    FALSE, p_table_name, /* table_name */
 				    FALSE, this_col_pname, /* column name */
 				    TRUE, v1, /* ordinal_position */
 				    FALSE, gda_data_model_get_value_at (tmpmodel, 4, i), /* column default */
@@ -512,57 +469,8 @@
 
 gboolean
 _gda_sqlite_meta_columns (GdaServerProvider *prov, GdaConnection *cnc, 
-			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
-{
-	gboolean retval = TRUE;
-	GdaDataModel *mod_model = NULL;
-	SqliteConnectionData *cdata;
-	
-	cdata = (SqliteConnectionData*) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
-		return FALSE;
-
-	mod_model = gda_meta_store_create_modify_data_model (store, context->table_name);
-	g_assert (mod_model);
-
-	GdaDataModel *tmpmodel;
-	
-	tmpmodel = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_TABLES, error, 0);
-	if (!tmpmodel)
-		retval = TRUE;
-	else {
-		gint nrows, i;
-		nrows = gda_data_model_get_n_rows (tmpmodel);
-		for (i = 0; i < nrows; i++) {
-			const GValue *p_table_name = gda_data_model_get_value_at (tmpmodel, 0, i);
-			const GValue *p_table_schema = gda_data_model_get_value_at (tmpmodel, 1, i);
-			if (!fill_columns_model (cnc, cdata, mod_model, p_table_schema, p_table_name, NULL, error)) {
-				retval = FALSE;
-				break;
-			}
-		}
-		g_object_unref (tmpmodel);
-	}
-	
-	if (retval)
-		retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
-	g_object_unref (mod_model);
-
-	return retval;
-}
-
-gboolean
-_gda_sqlite_meta_columns_t (GdaServerProvider *prov, GdaConnection *cnc, 
-			    GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-			    const GValue *table_schema, const GValue *table_name)
-{
-	return _gda_sqlite_meta_columns_c (prov, cnc, store, context, error, table_schema, table_name, NULL);
-}
-
-gboolean
-_gda_sqlite_meta_columns_c (GdaServerProvider *prov, GdaConnection *cnc, 
-			    GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-			    const GValue *table_schema, const GValue *table_name, const GValue *column_name)
+			  GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+			  const GValue *table_catalog, const GValue *table_schema, const GValue *table_name)
 {
 	gboolean retval = TRUE;
 	GdaDataModel *mod_model = NULL;
@@ -575,7 +483,7 @@
 	mod_model = gda_meta_store_create_modify_data_model (store, context->table_name);
 	g_assert (mod_model);
 
-	retval = fill_columns_model (cnc, cdata, mod_model, table_schema, table_name, column_name, error);	
+	retval = fill_columns_model (cnc, cdata, mod_model, table_schema, table_name, error);	
 	if (retval)
 		retval = gda_meta_store_modify_with_context (store, context, mod_model, error);
 	g_object_unref (mod_model);
@@ -583,39 +491,26 @@
 	return retval;
 }
 
-gboolean
-_gda_sqlite_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
-				  GdaMetaStore *store, GdaMetaContext *context, GError **error)
-{
-	TO_IMPLEMENT;
-	return TRUE;
-}
-
 gboolean 
-_gda_sqlite_meta_constraints_tab_s (GdaServerProvider *prov, GdaConnection *cnc, 
-				    GdaMetaStore *store, GdaMetaContext *context, GError **error,
-				    const GValue *table_schema, const GValue *table_name)
+_gda_sqlite_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
+				  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				  const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+				  const GValue *constraint_name_n)
 {
-	TO_IMPLEMENT;
+	/* not implemented in SQLite */
 	return TRUE;
 }
 
 gboolean
 _gda_sqlite_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
-				  GdaMetaStore *store, GdaMetaContext *context, GError **error)
+				  GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				  const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+				  const GValue *constraint_name)
 {
-	TO_IMPLEMENT;
+	/* not implemented in SQLite */
 	return TRUE;
 }
 
-gboolean
-_gda_sqlite_meta_constraints_ref_c (GdaServerProvider *prov, GdaConnection *cnc, 
-				    GdaMetaStore *store, GdaMetaContext *context, GError **error,
-				    const GValue *table_schema, const GValue *table_name)
-{
-	TO_IMPLEMENT;
-	return TRUE;
-}
 
 /*
  * @...: a list of TRUE/FALSE, GValue*  -- if TRUE then the following GValue must be freed

Modified: trunk/libgda/sqlite/gda-sqlite-meta.h
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-meta.h	(original)
+++ trunk/libgda/sqlite/gda-sqlite-meta.h	Wed Mar 12 21:18:24 2008
@@ -31,29 +31,18 @@
 					    GdaMetaStore *store, GdaMetaContext *context, GError **error);
 gboolean _gda_sqlite_meta_btypes           (GdaServerProvider *prov, GdaConnection *cnc, 
 					    GdaMetaStore *store, GdaMetaContext *context, GError **error);
-gboolean _gda_sqlite_meta_schemata         (GdaServerProvider *prov, GdaConnection *cnc, 
-					    GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					    const GValue *schema_name);
-gboolean _gda_sqlite_meta_tables_views     (GdaServerProvider *prov, GdaConnection *cnc, 
-					    GdaMetaStore *store, GdaMetaContext *context, GError **error);
-gboolean _gda_sqlite_meta_tables_views_s   (GdaServerProvider *prov, GdaConnection *cnc, 
-					    GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					    const GValue *table_schema, const GValue *table_name);
-gboolean _gda_sqlite_meta_columns           (GdaServerProvider *prov, GdaConnection *cnc, 
-					     GdaMetaStore *store, GdaMetaContext *context, GError **error);
-gboolean _gda_sqlite_meta_columns_t         (GdaServerProvider *prov, GdaConnection *cnc, 
-					     GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					     const GValue *table_schema, const GValue *table_name);
-gboolean _gda_sqlite_meta_columns_c         (GdaServerProvider *prov, GdaConnection *cnc, 
-					     GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					     const GValue *table_schema, const GValue *table_name, const GValue *column_name);
-gboolean _gda_sqlite_meta_constraints_tab   (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-gboolean _gda_sqlite_meta_constraints_tab_s (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-					     const GValue *table_schema, const GValue *table_name);
-
-gboolean _gda_sqlite_meta_constraints_ref   (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-gboolean _gda_sqlite_meta_constraints_ref_c (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-					     const GValue *table_schema, const GValue *table_name);
+gboolean _gda_sqlite_meta_schemata         (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
+					    const GValue *catalog_name, const GValue *schema_name_n);
+gboolean _gda_sqlite_meta_tables_views     (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n);
+gboolean _gda_sqlite_meta_columns          (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name);
+gboolean _gda_sqlite_meta_constraints_tab  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+					    const GValue *constraint_name_n);
+gboolean _gda_sqlite_meta_constraints_ref  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+					    const GValue *constraint_name);
 G_END_DECLS
 
 #endif

Modified: trunk/libgda/sqlite/gda-sqlite-provider.c
==============================================================================
--- trunk/libgda/sqlite/gda-sqlite-provider.c	(original)
+++ trunk/libgda/sqlite/gda-sqlite-provider.c	Wed Mar 12 21:18:24 2008
@@ -227,18 +227,13 @@
 	provider_class->statement_execute = gda_sqlite_provider_statement_execute;
 
 	memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
-	provider_class->meta_funcs.info = _gda_sqlite_meta_info;
-	provider_class->meta_funcs.btypes = _gda_sqlite_meta_btypes;
+	provider_class->meta_funcs._info = _gda_sqlite_meta_info;
+	provider_class->meta_funcs._btypes = _gda_sqlite_meta_btypes;
 	provider_class->meta_funcs.schemata = _gda_sqlite_meta_schemata;
 	provider_class->meta_funcs.tables_views = _gda_sqlite_meta_tables_views;
-	provider_class->meta_funcs.tables_views_s = _gda_sqlite_meta_tables_views_s;
 	provider_class->meta_funcs.columns = _gda_sqlite_meta_columns;
-	provider_class->meta_funcs.columns_t = _gda_sqlite_meta_columns_t;
-	provider_class->meta_funcs.columns_c = _gda_sqlite_meta_columns_c;
 	provider_class->meta_funcs.constraints_tab = _gda_sqlite_meta_constraints_tab;
-	provider_class->meta_funcs.constraints_tab_s = _gda_sqlite_meta_constraints_tab_s;
 	provider_class->meta_funcs.constraints_ref = _gda_sqlite_meta_constraints_ref;
-	provider_class->meta_funcs.constraints_ref_c = _gda_sqlite_meta_constraints_ref_c;
 }
 
 static void
@@ -479,7 +474,6 @@
 				     GdaQuarkList *params, GdaQuarkList *auth,
 				     guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data)
 {
-	static gint nb_opened = 1;
 	gchar *filename = NULL;
 	const gchar *dirname = NULL, *dbname = NULL;
 	const gchar *is_virtual = NULL;
@@ -581,12 +575,11 @@
 	opening_cdata = cdata;
 #endif
 
-	errmsg = sqlite3_open (filename, &cdata->connection);
-	g_print ("SQLite opened %d connection(s)\n", nb_opened++);
-
 	if (filename)
 		cdata->file = g_strdup (filename);
 
+	errmsg = sqlite3_open (filename, &cdata->connection);
+
 	if (errmsg != SQLITE_OK) {
 		gda_connection_add_event_string (cnc, sqlite3_errmsg (cdata->connection));
 		gda_sqlite_free_cnc_data (cdata);
@@ -596,6 +589,7 @@
 #endif
 		return FALSE;
 	}
+
 	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_sqlite_free_cnc_data);
 
 	/* use extended result codes */

Modified: trunk/libgda/sqlite/utils.c
==============================================================================
--- trunk/libgda/sqlite/utils.c	(original)
+++ trunk/libgda/sqlite/utils.c	Wed Mar 12 21:18:24 2008
@@ -73,6 +73,22 @@
 	return aff;
 }
 
+static guint
+nocase_str_hash (gconstpointer v)
+{
+	guint ret;
+	gchar *up = g_ascii_strup ((gchar *) v, -1);
+	ret = g_str_hash ((gconstpointer) up);
+	g_free (up);
+	return ret;
+}
+
+static gboolean
+nocase_str_equal (gconstpointer v1, gconstpointer v2)
+{
+	return g_ascii_strcasecmp ((gchar *) v1, (gchar *) v2) == 0 ? TRUE : FALSE;
+}
+
 void
 _gda_sqlite_update_types_hash (SqliteConnectionData *cdata)
 {
@@ -82,7 +98,7 @@
 
 	types = cdata->types;
 	if (!types) {
-		types = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* key= type name, value= gda type */
+		types = g_hash_table_new_full (nocase_str_hash, nocase_str_equal, g_free, NULL); /* key= type name, value= gda type */
 		cdata->types = types;
 	}
 	
@@ -93,6 +109,7 @@
 	g_hash_table_insert (types, g_strdup ("timestamp"), GINT_TO_POINTER (GDA_TYPE_TIMESTAMP));
 	g_hash_table_insert (types, g_strdup ("real"), GINT_TO_POINTER (G_TYPE_DOUBLE));
 	g_hash_table_insert (types, g_strdup ("text"), GINT_TO_POINTER (G_TYPE_STRING));
+	g_hash_table_insert (types, g_strdup ("string"), GINT_TO_POINTER (G_TYPE_STRING));
 	g_hash_table_insert (types, g_strdup ("blob"), GINT_TO_POINTER (GDA_TYPE_BINARY));
 
 	/* HACK: force SQLite to reparse the schema and thus discover new tables if necessary */

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Wed Mar 12 21:18:24 2008
@@ -1,3 +1,4 @@
+doc/C/prov-writing.xml
 libgda/gda-batch.c
 libgda/gda-config.c
 libgda/gda-connection.c
@@ -110,6 +111,7 @@
 providers/mysql/mysql_specs_drop_view.xml.in
 providers/mysql/mysql_specs_dsn.xml.in
 providers/mysql/mysql_specs_rename_table.xml.in
+providers/odbc/gda-odbc-provider.c
 providers/odbc/gda-odbc-recordset.c
 providers/odbc/libmain.c
 providers/odbc/odbc_specs_dsn.xml.in
@@ -158,9 +160,12 @@
 providers/sqlite/sqlite_specs_drop_view.xml.in
 providers/sqlite/sqlite_specs_dsn.xml.in
 providers/sqlite/sqlite_specs_rename_table.xml.in
+providers/sybase/gda-sybase-provider.c
 providers/sybase/gda-sybase-recordset.c
+providers/sybase/gda-sybase-types.c
 providers/sybase/libmain.c
 providers/sybase/sybase_specs_dsn.xml.in
+providers/sybase/utils.c
 providers/xbase/gda-xbase-provider.c
 providers/xbase/libmain.c
 providers/xbase/xbase_specs_dsn.xml.in

Modified: trunk/po/POTFILES.skip
==============================================================================
--- trunk/po/POTFILES.skip	(original)
+++ trunk/po/POTFILES.skip	Wed Mar 12 21:18:24 2008
@@ -1,3 +1,7 @@
+libgda/sql-parser/delimiter.c
+libgda/sql-parser/parser.c
+libgda/sqlite/sqlite-src/sqlite3.c
+providers/postgres/parser.c
 providers/skel-implementation/capi/capi_specs_create_table.xml.in
 providers/skel-implementation/capi/capi_specs_dsn.xml.in
 providers/skel-implementation/capi/gda-capi-blob-op.c

Modified: trunk/providers/postgres/gda-postgres-ddl.c
==============================================================================
--- trunk/providers/postgres/gda-postgres-ddl.c	(original)
+++ trunk/providers/postgres/gda-postgres-ddl.c	Wed Mar 12 21:18:24 2008
@@ -25,8 +25,79 @@
 #include "gda-postgres-ddl.h"
 
 gchar *
+gda_postgres_render_CREATE_DB (GdaServerProvider *provider, GdaConnection *cnc, 
+			       GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("CREATE DATABASE ");
+
+	value = gda_server_operation_get_value_at (op, "/DB_DEF_P/DB_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append_printf (string, "\"%s\"", g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/DB_DEF_P/OWNER");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		g_string_append (string, " OWNER ");
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	value = gda_server_operation_get_value_at (op, "/DB_DEF_P/TEMPLATE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		g_string_append (string, " TEMPLATE ");
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	value = gda_server_operation_get_value_at (op, "/DB_DEF_P/DB_CSET");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		GdaDataHandler *dh;
+		gchar *str;
+		
+		dh = gda_server_provider_get_data_handler_gtype (provider, cnc, G_TYPE_STRING);
+		str = gda_data_handler_get_sql_from_value (dh, value);
+
+		g_string_append (string, " ENCODING ");
+		g_string_append (string, str);
+		g_free (str);
+	}
+
+	value = gda_server_operation_get_value_at (op, "/DB_DEF_P/TABLESPACE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		g_string_append (string, " TABLESPACE ");
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;	
+}
+
+gchar *
+gda_postgres_render_DROP_DB (GdaServerProvider *provider, GdaConnection *cnc, 
+			     GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("DROP DATABASE ");
+
+	value = gda_server_operation_get_value_at (op, "/DB_DESC_P/DB_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append_printf (string, "\"%s\"", g_value_get_string (value));
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;	
+}
+
+gchar *
 gda_postgres_render_CREATE_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
-			      GdaServerOperation *op, GError **error)
+				  GdaServerOperation *op, GError **error)
 {
 	GString *string;
 	const GValue *value;
@@ -39,8 +110,11 @@
 	gint nbpkfields = 0;
 	gchar *sql = NULL;
 
-	/* CREATE TABLE */
-	string = g_string_new ("CREATE TABLE ");
+	string = g_string_new ("CREATE ");
+	value = gda_server_operation_get_value_at (op, "/TABLE_DEF_P/TABLE_TEMP");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+		g_string_append (string, "TEMP ");
+	g_string_append (string, "TABLE ");
 
 	value = gda_server_operation_get_value_at (op, "/TABLE_DEF_P/TABLE_NAME");
 	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
@@ -74,9 +148,12 @@
 				g_string_append (string, ", ");
 				
 			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NAME/%d", i);
+			g_string_append_c (string, '\"');
 			g_string_append (string, g_value_get_string (value));
+			g_string_append_c (string, '\"');
 			g_string_append_c (string, ' ');
-			
+				
+
 			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_AUTOINC/%d", i);
 			if (value)
 				g_string_append (string, "serial");
@@ -85,6 +162,17 @@
 				g_string_append (string, g_value_get_string (value));
 			}
 				
+			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_SIZE/%d", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_UINT)) {
+				g_string_append_printf (string, "(%d", g_value_get_uint (value));
+
+				value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_SCALE/%d", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_UINT))
+					g_string_append_printf (string, ",%d)", g_value_get_uint (value));
+				else
+					g_string_append (string, ")");
+			}
+				
 			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_DEFAULT/%d", i);
 			if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
 				const gchar *str = g_value_get_string (value);
@@ -97,7 +185,7 @@
 			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_NNUL/%d", i);
 			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
 				g_string_append (string, " NOT NULL");
-
+				
 			value = gda_server_operation_get_value_at (op, "/FIELDS_A/@COLUMN_UNIQUE/%d", i);
 			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
 				g_string_append (string, " UNIQUE");
@@ -118,6 +206,33 @@
 				}
 			}
 		}
+
+		/* LIKE inheritance */
+		nrows = gda_server_operation_get_sequence_size (op, "/TABLE_PARENTS_S");
+		for (i = 0; i < nrows; i++) {
+			value = gda_server_operation_get_value_at (op, "/TABLE_PARENTS_S/%d/TABLE_PARENT_COPY", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && !g_value_get_boolean (value)) {
+				value = gda_server_operation_get_value_at (op, "/TABLE_PARENTS_S/%d/TABLE_PARENT_TABLE", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+					const gchar *str = g_value_get_string (value);
+					if (str && *str) {
+						hasfields = TRUE;
+						if (first) 
+							first = FALSE;
+						else
+							g_string_append (string, ", ");
+
+						g_string_append (string, "LIKE ");
+						g_string_append (string, str);
+						value = gda_server_operation_get_value_at (op, 
+											   "/TABLE_PARENTS_S/%d/TABLE_PARENT_COPY_DEFAULTS", i);
+						if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && 
+						    g_value_get_boolean (value))
+							g_string_append (string, " INCLUDING DEFAULTS");
+					}
+				}
+			}
+		}
 	}
 
 	/* composed primary key */
@@ -128,20 +243,397 @@
 		while (list) {
 			if (list != pkfields)
 				g_string_append (string, ", ");
+			g_string_append_c (string, '\"');
 			g_string_append (string, g_value_get_string ((GValue*) list->data));
+			g_string_append_c (string, '\"');
 			list = list->next;
 		}
 		g_string_append_c (string, ')');
 	}
 
+	/* foreign keys */
+	if (allok) {
+		GdaServerOperationNode *node;
+
+		first = TRUE;
+		node = gda_server_operation_get_node_info (op, "/FKEY_S");
+		if (node) {
+			nrows = gda_server_operation_get_sequence_size (op, "/FKEY_S");
+			for (i = 0; i < nrows; i++) {
+				gint nbfields, j;
+
+				g_string_append (string, ", FOREIGN KEY (");
+				node = gda_server_operation_get_node_info (op, "/FKEY_S/%d/FKEY_FIELDS_A", i);
+				if (!node || ((nbfields = gda_data_model_get_n_rows (node->model)) == 0)) {
+					allok = FALSE;
+					g_set_error (error, 0, 0, _("No field specified in foreign key constraint"));
+				}
+				else {
+					for (j = 0; j < nbfields; j++) {
+						if (j != 0)
+							g_string_append (string, ", ");
+						value = gda_server_operation_get_value_at (op, 
+											   "/FKEY_S/%d/FKEY_FIELDS_A/@FK_FIELD/%d", i, j);
+						if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+						{
+							g_string_append_c (string, '\"');
+							g_string_append (string, g_value_get_string (value));
+							g_string_append_c (string, '\"');
+						}
+						else {
+							allok = FALSE;
+							g_set_error (error, 0, 0, 
+								     _("Empty field specified in foreign key constraint"));
+						}
+					}
+				}
+				g_string_append (string, ") REFERENCES ");
+				value = gda_server_operation_get_value_at (op, "/FKEY_S/%d/FKEY_REF_TABLE", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+					g_string_append (string, g_value_get_string (value));
+				else {
+					allok = FALSE;
+					g_set_error (error, 0, 0, _("No referenced table specified in foreign key constraint"));
+				}
+
+				g_string_append (string, " (");
+				for (j = 0; j < nbfields; j++) {
+					if (j != 0)
+						g_string_append (string, ", ");
+					value = gda_server_operation_get_value_at (op, 
+										   "/FKEY_S/%d/FKEY_FIELDS_A/@FK_REF_PK_FIELD/%d", i, j);
+					if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+					{
+						g_string_append_c (string, '\"');
+						g_string_append (string, g_value_get_string (value));
+						g_string_append_c (string, '\"');
+					}
+					else {
+						allok = FALSE;
+						g_set_error (error, 0, 0, 
+							     _("Empty referenced field specified in foreign key constraint"));
+					}
+				}
+				g_string_append_c (string, ')');
+				value = gda_server_operation_get_value_at (op, "/FKEY_S/%d/FKEY_MATCH_TYPE", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+					g_string_append_printf (string, " %s", g_value_get_string (value));
+				value = gda_server_operation_get_value_at (op, "/FKEY_S/%d/FKEY_ONUPDATE", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+					g_string_append_printf (string, " ON UPDATE %s", g_value_get_string (value));
+				value = gda_server_operation_get_value_at (op, "/FKEY_S/%d/FKEY_ONDELETE", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+					g_string_append_printf (string, " ON DELETE %s", g_value_get_string (value));
+				value = gda_server_operation_get_value_at (op, "/FKEY_S/%d/FKEY_DEFERRABLE", i);
+				if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value))
+					g_string_append_printf (string, " %s", g_value_get_string (value));
+			}
+		}
+	}
+
 	g_string_append (string, ")");
 
+	/* INHERITS */
+	first = TRUE;
+	nrows = gda_server_operation_get_sequence_size (op, "/TABLE_PARENTS_S");
+	for (i = 0; i < nrows; i++) {
+		value = gda_server_operation_get_value_at (op, "/TABLE_PARENTS_S/%d/TABLE_PARENT_COPY", i);
+		if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value)) {
+			value = gda_server_operation_get_value_at (op, "/TABLE_PARENTS_S/%d/TABLE_PARENT_TABLE", i);
+			if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+				const gchar *str = g_value_get_string (value);
+				if (str && *str) {
+					hasfields = TRUE;
+					if (first) {
+						g_string_append (string, " INHERITS ");
+						first = FALSE;
+					}
+					else
+						g_string_append (string, ", ");
+					g_string_append (string, str);
+				}
+			}
+		}
+	}
+
 	if (!hasfields) {
 		allok = FALSE;
 		g_set_error (error, 0, 0, _("Table to create must have at least one row"));
 	}
+
+	if (allok) {
+		value = gda_server_operation_get_value_at (op, "/TABLE_DEF_P/TABLE_WITH_OIDS");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+			g_string_append (string, " WITH OIDS");
+	}
+
 	g_slist_free (pkfields);
 
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}
+
+gchar *
+gda_postgres_render_DROP_TABLE   (GdaServerProvider *provider, GdaConnection *cnc, 
+				  GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("DROP TABLE ");
+
+	value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/TABLE_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/REFERENCED_ACTION");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+		g_string_append_c (string, ' ');
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}
+
+gchar *
+gda_postgres_render_RENAME_TABLE (GdaServerProvider *provider, GdaConnection *cnc, 
+				  GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("ALTER TABLE ");
+
+	value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/TABLE_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/TABLE_DESC_P/TABLE_NEW_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, " RENAME TO ");
+	g_string_append (string, g_value_get_string (value));
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}
+
+
+gchar *
+gda_postgres_render_ADD_COLUMN (GdaServerProvider *provider, GdaConnection *cnc, 
+				GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("ALTER TABLE ");
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/TABLE_ONLY");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+		g_string_append (string, "ONLY ");
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/TABLE_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	g_string_append (string, " ADD COLUMN ");
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_TYPE");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append_c (string, ' ');
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_SIZE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_UINT)) {
+		g_string_append_printf (string, "(%d", g_value_get_uint (value));
+
+		value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_SCALE");
+		if (value && G_VALUE_HOLDS (value, G_TYPE_UINT))
+			g_string_append_printf (string, ",%d)", g_value_get_uint (value));
+		else
+			g_string_append (string, ")");
+	}
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_DEFAULT");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+		const gchar *str = g_value_get_string (value);
+		if (str && *str) {
+			g_string_append (string, " DEFAULT ");
+			g_string_append (string, str);
+		}
+	}
+				
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_NNUL");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+		g_string_append (string, " NOT NULL");
+				
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_UNIQUE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+		g_string_append (string, " UNIQUE");
+	
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_PKEY");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_BOOLEAN) && g_value_get_boolean (value))
+		g_string_append (string, " PRIMARY KEY");
+				
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DEF_P/COLUMN_CHECK");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+		const gchar *str = g_value_get_string (value);
+		if (str && *str) {
+			g_string_append (string, " CHECK (");
+			g_string_append (string, str);
+			g_string_append_c (string, ')');
+		}
+	}
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}
+
+gchar *
+gda_postgres_render_DROP_COLUMN  (GdaServerProvider *provider, GdaConnection *cnc, 
+				  GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("ALTER TABLE ");
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DESC_P/TABLE_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DESC_P/COLUMN_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, " DROP COLUMN ");
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/COLUMN_DESC_P/REFERENCED_ACTION");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+		const gchar *str = g_value_get_string (value);
+		if (str && *str) {
+			g_string_append_c (string, ' ');
+			g_string_append (string, str);
+		}
+	}
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}
+
+
+gchar *
+gda_postgres_render_CREATE_INDEX (GdaServerProvider *provider, GdaConnection *cnc, 
+				  GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+	GdaServerOperationNode *node;
+	gint nrows, i;
+
+	string = g_string_new ("CREATE ");
+
+	value = gda_server_operation_get_value_at (op, "/INDEX_DEF_P/INDEX_TYPE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && 
+	    g_value_get_string (value) && *g_value_get_string (value)) {
+		g_string_append (string, g_value_get_string (value));
+		g_string_append_c (string, ' ');
+	}
+
+	g_string_append (string, "INDEX ");
+
+	value = gda_server_operation_get_value_at (op, "/INDEX_DEF_P/INDEX_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	g_string_append (string, " ON ");
+	
+	value = gda_server_operation_get_value_at (op, "/INDEX_DEF_P/INDEX_ON_TABLE");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/INDEX_DEF_P/INDEX_METHOD");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		g_string_append (string, " USING ");
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	/* fields or expressions the index is on */
+	g_string_append (string, " (");
+	node = gda_server_operation_get_node_info (op, "/INDEX_FIELDS_S");
+	g_assert (node);
+	nrows = gda_server_operation_get_sequence_size (op, "/INDEX_FIELDS_S");
+	for (i = 0; i < nrows; i++) {
+		value = gda_server_operation_get_value_at (op, "/INDEX_FIELDS_S/%d/INDEX_FIELD", i);
+		if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+			if (i != 0)
+				g_string_append (string, ", ");
+			g_string_append_c (string, '\"');
+			g_string_append (string, g_value_get_string (value));
+			g_string_append_c (string, '\"');
+		}
+	}
+
+	g_string_append (string, ")");
+
+	/* options */
+	value = gda_server_operation_get_value_at (op, "/INDEX_DEF_P/INDEX_TABLESPACE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		g_string_append (string, " TABLESPACE ");
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	value = gda_server_operation_get_value_at (op, "/INDEX_DEF_P/INDEX_PREDICATE");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING) && g_value_get_string (value)) {
+		g_string_append (string, " WHERE ");
+		g_string_append (string, g_value_get_string (value));
+	}
+
+	sql = string->str;
+	g_string_free (string, FALSE);
+
+	return sql;
+}
+
+gchar *
+gda_postgres_render_DROP_INDEX   (GdaServerProvider *provider, GdaConnection *cnc, 
+				  GdaServerOperation *op, GError **error)
+{
+	GString *string;
+	const GValue *value;
+	gchar *sql = NULL;
+
+	string = g_string_new ("DROP INDEX ");
+
+	value = gda_server_operation_get_value_at (op, "/INDEX_DESC_P/INDEX_NAME");
+	g_assert (value && G_VALUE_HOLDS (value, G_TYPE_STRING));
+	g_string_append (string, g_value_get_string (value));
+
+	value = gda_server_operation_get_value_at (op, "/INDEX_DESC_P/REFERENCED_ACTION");
+	if (value && G_VALUE_HOLDS (value, G_TYPE_STRING)) {
+		g_string_append_c (string, ' ');
+		g_string_append (string, g_value_get_string (value));
+	}
+
 	sql = string->str;
 	g_string_free (string, FALSE);
 

Modified: trunk/providers/postgres/gda-postgres-meta.c
==============================================================================
--- trunk/providers/postgres/gda-postgres-meta.c	(original)
+++ trunk/providers/postgres/gda-postgres-meta.c	Wed Mar 12 21:18:24 2008
@@ -41,16 +41,15 @@
 typedef enum {
         I_STMT_CATALOG,
 	I_STMT_BTYPES,
-	I_STMT_SCHEMATA,
+	I_STMT_SCHEMAS,
+	I_STMT_SCHEMA_NAMED,
 	I_STMT_TABLES,
+	I_STMT_TABLE_NAMED,
 	I_STMT_VIEWS,
-	I_STMT_TABLES_S,
-	I_STMT_VIEWS_S,
-	I_STMT_ALLCOLUMNS,
+	I_STMT_VIEW_NAMED,
 	I_STMT_COLUMNS_OF_TABLE,
-	I_STMT_ALL_TABLES_CONSTRAINTS,
-	I_STMT_TABLE_CONSTRAINTS,
-	I_STMT_ALL_REF_CONSTRAINTS,
+	I_STMT_TABLES_CONSTRAINTS,
+	I_STMT_TABLES_CONSTRAINT_NAMED,
 	I_STMT_REF_CONSTRAINTS
 } InternalStatementItem;
 
@@ -61,30 +60,39 @@
 static gchar *internal_sql[] = {
 	/* I_STMT_CATALOG */
 	"SELECT pg_catalog.current_database()",
+
 	/* I_STMT_BTYPES */
 	"SELECT t.typname, 'pg_catalog.' || t.typname, 'gchararray', pg_catalog.obj_description(t.oid), NULL, CASE WHEN t.typname ~ '^_' THEN TRUE WHEN typtype = 'p' THEN TRUE WHEN t.typname in ('any', 'anyarray', 'anyelement', 'cid', 'cstring', 'int2vector', 'internal', 'language_handler', 'oidvector', 'opaque', 'record', 'refcursor', 'regclass', 'regoper', 'regoperator', 'regproc', 'regprocedure', 'regtype', 'SET', 'smgr', 'tid', 'trigger', 'unknown', 'void', 'xid', 'oid', 'aclitem') THEN TRUE ELSE FALSE END, CAST (t.oid AS int8) FROM pg_catalog.pg_type t, pg_catalog.pg_user u, pg_catalog.pg_namespace n WHERE t.typowner=u.usesysid AND n.oid = t.typnamespace AND pg_catalog.pg_type_is_visible(t.oid) AND (typtype='b' OR typtype='p')",
-	/* I_STMT_SCHEMATA */
-	"SELECT catalog_name, schema_name, schema_owner, CASE WHEN schema_name ~'^pg_' THEN TRUE WHEN schema_name ='information_schema' THEN TRUE ELSE FALSE END FROM information_schema.schemata",
+
+	/* I_STMT_SCHEMAS */
+	"SELECT catalog_name, schema_name, schema_owner, CASE WHEN schema_name ~'^pg_' THEN TRUE WHEN schema_name ='information_schema' THEN TRUE ELSE FALSE END FROM information_schema.schemata WHERE catalog_name = ##cat::string",
+
+	/* I_STMT_SCHEMA_NAMED */
+	"SELECT catalog_name, schema_name, schema_owner, CASE WHEN schema_name ~'^pg_' THEN TRUE WHEN schema_name ='information_schema' THEN TRUE ELSE FALSE END FROM information_schema.schemata WHERE catalog_name = ##cat::string AND schema_name = ##name::string",
+
 	/* I_STMT_TABLES */
-	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, CASE WHEN nc.oid = pg_my_temp_schema() THEN 'LOCAL TEMPORARY'::text WHEN c.relkind = 'r' THEN 'BASE TABLE' WHEN c.relkind = 'v' THEN 'VIEW' ELSE NULL::text END::information_schema.character_data AS table_type, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.obj_description(c.oid), CASE WHEN pg_catalog.pg_table_is_visible(c.oid) IS TRUE AND nc.nspname!='pg_catalog' THEN c.relname ELSE coalesce (nc.nspname || '.', '') || c.relname END, coalesce (nc.nspname || '.', '') || c.relname, o.rolname FROM pg_namespace nc, pg_class c, pg_authid o WHERE c.relnamespace = nc.oid AND (c.relkind = ANY (ARRAY['r', 'v'])) AND NOT pg_is_other_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid,
  'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text)) AND o.oid=c.relowner",
+	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, CASE WHEN nc.oid = pg_my_temp_schema() THEN 'LOCAL TEMPORARY'::text WHEN c.relkind = 'r' THEN 'BASE TABLE' WHEN c.relkind = 'v' THEN 'VIEW' ELSE NULL::text END::information_schema.character_data AS table_type, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.obj_description(c.oid), CASE WHEN pg_catalog.pg_table_is_visible(c.oid) IS TRUE AND nc.nspname!='pg_catalog' THEN c.relname ELSE coalesce (nc.nspname || '.', '') || c.relname END, coalesce (nc.nspname || '.', '') || c.relname, o.rolname FROM pg_namespace nc, pg_class c, pg_authid o WHERE current_database()::information_schema.sql_identifier = ##cat::string AND nc.nspname::information_schema.sql_identifier = ##schema::string AND c.relnamespace = nc.oid AND (c.relkind = ANY (ARRAY['r', 'v'])) AND NOT pg_is_ot
 her_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text)) AND o.oid=c.relowner",
+
+	/* I_STMT_TABLE_NAMED */
+	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, CASE WHEN nc.oid = pg_my_temp_schema() THEN 'LOCAL TEMPORARY'::text WHEN c.relkind = 'r' THEN 'BASE TABLE' WHEN c.relkind = 'v' THEN 'VIEW' ELSE NULL::text END::information_schema.character_data AS table_type, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.obj_description(c.oid), CASE WHEN pg_catalog.pg_table_is_visible(c.oid) IS TRUE AND nc.nspname!='pg_catalog' THEN c.relname ELSE coalesce (nc.nspname || '.', '') || c.relname END, coalesce (nc.nspname || '.', '') || c.relname, o.rolname FROM pg_namespace nc, pg_class c, pg_authid o WHERE current_database()::information_schema.sql_identifier = ##cat::string AND nc.nspname::information_schema.sql_identifier = ##schema::string AND c.relnamespace = nc.oid AND (c.relkind = ANY (ARRAY['r', 'v'])) AND NOT pg_is_ot
 her_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text)) AND o.oid=c.relowner AND c.relname::information_schema.sql_identifier = ##name::string",
+
 	/* I_STMT_VIEWS */
-	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, pg_catalog.pg_get_viewdef(c.oid, TRUE), NULL, CASE WHEN c.relkind = 'r'::\"char\" THEN TRUE ELSE FALSE END FROM pg_namespace nc, pg_class c WHERE c.relnamespace = nc.oid AND c.relkind = 'v' AND NOT pg_is_other_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text))",
-	/* I_STMT_TABLES_S */
-	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, CASE WHEN nc.oid = pg_my_temp_schema() THEN 'LOCAL TEMPORARY'::text WHEN c.relkind = 'r' THEN 'BASE TABLE' WHEN c.relkind = 'v' THEN 'VIEW' ELSE NULL::text END::information_schema.character_data AS table_type, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.obj_description(c.oid), CASE WHEN pg_catalog.pg_table_is_visible(c.oid) IS TRUE AND nc.nspname!='pg_catalog' THEN c.relname ELSE coalesce (nc.nspname || '.', '') || c.relname END, coalesce (nc.nspname || '.', '') || c.relname, o.rolname FROM pg_namespace nc, pg_class c, pg_authid o WHERE c.relnamespace = nc.oid AND (c.relkind = ANY (ARRAY['r', 'v'])) AND NOT pg_is_other_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid,
  'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text)) AND o.oid=c.relowner AND table_schema = ##schema::string",
-	/* I_STMT_VIEWS_S */
-	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, pg_catalog.pg_get_viewdef(c.oid, TRUE), NULL, CASE WHEN c.relkind = 'r'::\"char\" THEN TRUE ELSE FALSE END FROM pg_namespace nc, pg_class c WHERE c.relnamespace = nc.oid AND c.relkind = 'v' AND NOT pg_is_other_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text)) AND table_schema = ##schema::string",
-	/* I_STMT_ALLCOLUMNS */
-	"SELECT current_database(), nc.nspname, c.relname, a.attname, a.attnum, pg_get_expr(ad.adbin, ad.adrelid), CASE WHEN a.attnotnull OR t.typtype = 'd' AND t.typnotnull THEN FALSE ELSE TRUE END, coalesce (nt.nspname || '.', '') || t.typname, CASE WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN 1 ELSE 0 END, CASE WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN 'ARRAY' || 'COL' || current_database() || '.' || nc.nspname || '.' || c.relname || '.' || a.attnum ELSE NULL END, 'gchararray', information_schema._pg_char_max_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_char_octet_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_numeric_precision(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_numeric_scale(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truety
 pmod(a.*, t.*)), information_schema._pg_datetime_precision(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), NULL, NULL, NULL, NULL, NULL, NULL, CASE WHEN pg_get_expr(ad.adbin, ad.adrelid) LIKE 'nextval(%' THEN 'AUTO_INCREMENT' ELSE NULL END, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.col_description(c.oid, a.attnum), CAST (t.oid AS int8) FROM pg_attribute a LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum, pg_class c, pg_namespace nc, pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid) ON t.typtype = 'd' AND t.typbasetype = bt.oid WHERE a.attrelid = c.oid AND a.atttypid = t.oid AND nc.oid = c.relnamespace AND NOT pg_is_other_temp_schema(nc.oid) AND a.attnum > 0 AND NOT a.attisdropped AND (c.relkind = ANY (ARRAY['r', 'v'])) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text)
  OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text))",
+	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, pg_catalog.pg_get_viewdef(c.oid, TRUE), NULL, CASE WHEN c.relkind = 'r'::\"char\" THEN TRUE ELSE FALSE END FROM pg_namespace nc, pg_class c WHERE current_database()::information_schema.sql_identifier = ##cat::string AND nc.nspname::information_schema.sql_identifier = ##schema::string AND c.relnamespace = nc.oid AND c.relkind = 'v' AND NOT pg_is_other_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text))",
+
+	/* I_STMT_VIEW_NAMED */
+	"SELECT current_database()::information_schema.sql_identifier AS table_catalog, nc.nspname::information_schema.sql_identifier AS table_schema, c.relname::information_schema.sql_identifier AS table_name, pg_catalog.pg_get_viewdef(c.oid, TRUE), NULL, CASE WHEN c.relkind = 'r'::\"char\" THEN TRUE ELSE FALSE END FROM pg_namespace nc, pg_class c WHERE current_database()::information_schema.sql_identifier = ##cat::string AND nc.nspname::information_schema.sql_identifier = ##schema::string AND c.relnamespace = nc.oid AND c.relkind = 'v' AND NOT pg_is_other_temp_schema(nc.oid) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'DELETE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text) OR has_table_privilege(c.oid, 'TRIGGER'::text)) AND c.relname::information_schema.sql_identifier = ##name::string",
+
 	/* I_STMT_COLUMNS_OF_TABLE */
-	"SELECT current_database(), nc.nspname, c.relname, a.attname, a.attnum, pg_get_expr(ad.adbin, ad.adrelid), CASE WHEN a.attnotnull OR t.typtype = 'd' AND t.typnotnull THEN FALSE ELSE TRUE END, coalesce (nt.nspname || '.', '') || t.typname, CASE WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN 1 ELSE 0 END, CASE WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN 'ARRAY' || 'COL' || current_database() || '.' || nc.nspname || '.' || c.relname || '.' || a.attnum ELSE NULL END, 'gchararray', information_schema._pg_char_max_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_char_octet_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_numeric_precision(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_numeric_scale(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truety
 pmod(a.*, t.*)), information_schema._pg_datetime_precision(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), NULL, NULL, NULL, NULL, NULL, NULL, CASE WHEN pg_get_expr(ad.adbin, ad.adrelid) LIKE 'nextval(%' THEN 'AUTO_INCREMENT' ELSE NULL END, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.col_description(c.oid, a.attnum), CAST (t.oid AS int8) FROM pg_attribute a LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum, pg_class c, pg_namespace nc, pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid) ON t.typtype = 'd' AND t.typbasetype = bt.oid WHERE nc.nspname = ##schema::string AND c.relname = ##tblname::string AND a.attrelid = c.oid AND a.atttypid = t.oid AND nc.oid = c.relnamespace AND NOT pg_is_other_temp_schema(nc.oid) AND a.attnum > 0 AND NOT a.attisdropped AND (c.relkind = ANY (ARRAY['r', 'v'])) AND (pg_has_role(c.re
 lowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text))",
-	/* I_STMT_ALL_TABLES_CONSTRAINTS */
-	"SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, constraint_type, CASE WHEN is_deferrable = 'YES' THEN TRUE ELSE FALSE END, CASE WHEN initially_deferred = 'YES' THEN TRUE ELSE FALSE END FROM information_schema.table_constraints",
-	/* I_STMT_TABLE_CONSTRAINTS */
-	"SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, constraint_type, CASE WHEN is_deferrable = 'YES' THEN TRUE ELSE FALSE END, CASE WHEN initially_deferred = 'YES' THEN TRUE ELSE FALSE END FROM information_schema.table_constraints WHERE table_schema = ##schema::string AND table_name = ##tblname::string",
-	/* I_STMT_ALL_REF_CONSTRAINTS */
-	"SELECT constraint_catalog, constraint_schema, constraint_name, unique_constraint_catalog, unique_constraint_schema, unique_constraint_name, match_option, update_rule, delete_rule FROM information_schema.referential_constraints",
+	"SELECT current_database(), nc.nspname, c.relname, a.attname, a.attnum, pg_get_expr(ad.adbin, ad.adrelid), CASE WHEN a.attnotnull OR t.typtype = 'd' AND t.typnotnull THEN FALSE ELSE TRUE END, coalesce (nt.nspname || '.', '') || t.typname, CASE WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN 1 ELSE 0 END, CASE WHEN t.typelem <> 0::oid AND t.typlen = -1 THEN 'ARRAY' || 'COL' || current_database() || '.' || nc.nspname || '.' || c.relname || '.' || a.attnum ELSE NULL END, 'gchararray', information_schema._pg_char_max_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_char_octet_length(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_numeric_precision(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), information_schema._pg_numeric_scale(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truety
 pmod(a.*, t.*)), information_schema._pg_datetime_precision(information_schema._pg_truetypid(a.*, t.*), information_schema._pg_truetypmod(a.*, t.*)), NULL, NULL, NULL, NULL, NULL, NULL, CASE WHEN pg_get_expr(ad.adbin, ad.adrelid) LIKE 'nextval(%' THEN 'AUTO_INCREMENT' ELSE NULL END, CASE WHEN c.relkind = 'r' THEN TRUE ELSE FALSE END, pg_catalog.col_description(c.oid, a.attnum), CAST (t.oid AS int8) FROM pg_attribute a LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum, pg_class c, pg_namespace nc, pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid) ON t.typtype = 'd' AND t.typbasetype = bt.oid WHERE current_database() = ##cat::string AND nc.nspname = ##schema::string AND c.relname = ##name::string AND a.attrelid = c.oid AND a.atttypid = t.oid AND nc.oid = c.relnamespace AND NOT pg_is_other_temp_schema(nc.oid) AND a.attnum > 0 AND NOT a.attisdropped AND (c.relkind = ANY (ARR
 AY['r', 'v'])) AND (pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT'::text) OR has_table_privilege(c.oid, 'INSERT'::text) OR has_table_privilege(c.oid, 'UPDATE'::text) OR has_table_privilege(c.oid, 'REFERENCES'::text))",
+
+	/* I_STMT_TABLES_CONSTRAINTS */
+	"SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, constraint_type, NULL, CASE WHEN is_deferrable = 'YES' THEN TRUE ELSE FALSE END, CASE WHEN initially_deferred = 'YES' THEN TRUE ELSE FALSE END FROM information_schema.table_constraints WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string",
+
+	/* I_STMT_TABLES_CONSTRAINT_NAMED */
+	"SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, constraint_type, NULL, CASE WHEN is_deferrable = 'YES' THEN TRUE ELSE FALSE END, CASE WHEN initially_deferred = 'YES' THEN TRUE ELSE FALSE END FROM information_schema.table_constraints WHERE table_catalog = ##cat::string AND table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string",
+
 	/* I_STMT_REF_CONSTRAINTS */
-	"SELECT constraint_catalog, constraint_schema, constraint_name, unique_constraint_catalog, unique_constraint_schema, unique_constraint_name, match_option, update_rule, delete_rule FROM information_schema.referential_constraints WHERE constraint_schema = ##schema::string AND constraint_name = ##constname::string"
+	" SELECT  current_database(), nt.nspname, t.relname, c.conname, current_database(), nref.nspname, ref.relname, pkc.conname, CASE c.confmatchtype WHEN 'f'::\"char\" THEN 'FULL'::text WHEN 'p'::\"char\" THEN 'PARTIAL'::text WHEN 'u'::\"char\" THEN 'NONE'::text ELSE NULL::text END AS match_option, CASE c.confupdtype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS update_rule, CASE c.confdeltype WHEN 'c'::\"char\" THEN 'CASCADE'::text WHEN 'n'::\"char\" THEN 'SET NULL'::text WHEN 'd'::\"char\" THEN 'SET DEFAULT'::text WHEN 'r'::\"char\" THEN 'RESTRICT'::text WHEN 'a'::\"char\" THEN 'NO ACTION'::text ELSE NULL::text END AS delete_rule FROM pg_constraint c INNER JOIN pg_class t ON (c.conrelid=t.oid) INNER JOIN pg_namespace nt ON (nt.oid=t.relnamespace) INNER JOIN pg_class ref ON (c.confrelid=ref.oid)
  INNER JOIN pg_namespace nref ON (nref.oid=ref.relnamespace) INNER JOIN pg_constraint pkc ON (c.confrelid = pkc.conrelid AND information_schema._pg_keysequal(c.confkey, pkc.conkey)) WHERE c.contype = 'f' AND current_database() = ##cat::string AND nt.nspname = ##schema::string AND t.relname = ##name::string AND c.conname = ##name2::string"
 };
 
 /*
@@ -97,7 +105,7 @@
  * global static values
  */
 static GdaSqlParser *internal_parser = NULL;
-static GdaSet       *pragma_set;
+static GdaSet       *i_set;
 
 
 /*
@@ -125,9 +133,10 @@
         }
 
 	/* initialize static values here */
-	pragma_set = gda_set_new_inline (3, "tblname", G_TYPE_STRING, "",
-					 "schema", G_TYPE_STRING, "",
-					 "constname", G_TYPE_STRING, "");
+	i_set = gda_set_new_inline (4, "cat", G_TYPE_STRING, "", 
+				    "name", G_TYPE_STRING, "",
+				    "name2", G_TYPE_STRING, "",
+				    "schema", G_TYPE_STRING, "");
 }
 
 gboolean
@@ -197,74 +206,62 @@
 gboolean 
 _gda_postgres_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc, 
 			     GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-			     const GValue *schema_name)
+			     const GValue *catalog_name, const GValue *schema_name_n)
 {
 	GdaDataModel *model;
 	gboolean retval;
 
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_SCHEMATA], NULL, error);
-	if (!model)
-		return FALSE;
-
-	retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
-	g_object_unref (model);
-
-	return retval;
-}
-
-
-
-gboolean
-_gda_postgres_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
-				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
-{
-	GdaDataModel *tables_model, *views_model;
-	gboolean retval = TRUE;
-
-	tables_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES], NULL, error);
-	if (!tables_model)
-		return FALSE;
-	views_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS], NULL, error);
-	if (!views_model) {
-		g_object_unref (tables_model);
-		return FALSE;
-	}
-
-	GdaMetaContext c2;
-	c2 = *context; /* copy contents, just because we need to modify @context->table_name */
-	if (retval) {
-		c2.table_name = "_tables";
-		retval = gda_meta_store_modify_with_context (store, &c2, tables_model, error);
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), catalog_name);
+	if (!schema_name_n) {
+		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_SCHEMAS], i_set, error);
+		if (!model)
+			return FALSE;
+		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
 	}
-	if (retval) {
-		c2.table_name = "_views";
-		retval = gda_meta_store_modify_with_context (store, &c2, views_model, error);
+	else {
+		gda_holder_set_value (gda_set_get_holder (i_set, "name"), schema_name_n);
+		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_SCHEMA_NAMED], i_set, error);
+		if (!model)
+			return FALSE;
+		
+		retval = gda_meta_store_modify (store, context->table_name, model, "schema_name = ##name::string", error, 
+						"name", schema_name_n, NULL);
 	}
-	g_object_unref (tables_model);
-	g_object_unref (views_model);
-
+	g_object_unref (model);
 
 	return retval;
 }
 
-
-
 gboolean 
-_gda_postgres_meta_tables_views_s (GdaServerProvider *prov, GdaConnection *cnc, 
-				   GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-				   const GValue *table_schema, const GValue *table_name)
+_gda_postgres_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
+				 GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+				 const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n)
 {
 	GdaDataModel *tables_model, *views_model;
 	gboolean retval = TRUE;
 
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "schema"), table_schema);
-	tables_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES_S], pragma_set, error);
-	if (!tables_model)
-		return FALSE;
-	views_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS_S], pragma_set, error);
-	if (!views_model) {
-		g_object_unref (tables_model);
-		return FALSE;
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	if (!table_name_n) {
+		tables_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES], i_set, error);
+		if (!tables_model)
+			return FALSE;
+		views_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEWS], i_set, error);
+		if (!views_model) {
+			g_object_unref (tables_model);
+			return FALSE;
+		}
+	}
+	else {
+		gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name_n);
+		tables_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLE_NAMED], i_set, error);
+		if (!tables_model)
+			return FALSE;
+		views_model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_VIEW_NAMED], i_set, error);
+		if (!views_model) {
+			g_object_unref (tables_model);
+			return FALSE;
+		}
 	}
 
 	GdaMetaContext c2;
@@ -286,55 +283,8 @@
 
 gboolean
 _gda_postgres_meta_columns (GdaServerProvider *prov, GdaConnection *cnc, 
-			    GdaMetaStore *store, GdaMetaContext *context, GError **error)
-{
-	GdaDataModel *model, *proxy;
-	gboolean retval = TRUE;
-	gint i, nrows;
-	PostgresConnectionData *cdata;
-
-	cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
-		return FALSE;
-
-	/* use a prepared statement for the "base" model */
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_ALLCOLUMNS], NULL, error);
-	if (!model)
-		return FALSE;
-
-	/* use a proxy to customize @model */
-	proxy = (GdaDataModel*) gda_data_proxy_new (model);
-	gda_data_proxy_set_sample_size ((GdaDataProxy*) proxy, 0);
-	nrows = gda_data_model_get_n_rows (model);
-	for (i = 0; i < nrows; i++) {
-		const GValue *value;
-		GType type;
-		value = gda_data_model_get_value_at (model, 25, i);
-		
-		type = _gda_postgres_type_oid_to_gda (cdata, g_value_get_int64 (value));
-		if (type != G_TYPE_STRING) {
-			GValue *v;
-			g_value_set_string (v = gda_value_new (G_TYPE_STRING), g_type_name (type));
-			retval = gda_data_model_set_value_at (proxy, 10, i, v, error);
-			gda_value_free (v);
-			if (!retval)
-				break;
-		}
-	}
-
-	/* modify meta store with @proxy */
-	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, proxy, NULL, error, NULL);
-	g_object_unref (proxy);
-	g_object_unref (model);
-
-	return retval;
-}
-
-gboolean
-_gda_postgres_meta_columns_t (GdaServerProvider *prov, GdaConnection *cnc, 
-			      GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-			      const GValue *table_schema, const GValue *table_name)
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error, 
+			    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name)
 {
 	GdaDataModel *model, *proxy;
 	gboolean retval = TRUE;
@@ -350,9 +300,10 @@
 		return FALSE;
 
 	/* use a prepared statement for the "base" model */
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "schema"), table_schema);
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "tblname"), table_name);
-	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_OF_TABLE], pragma_set, 
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name);
+	model = gda_connection_statement_execute_select_full (cnc, internal_stmt[I_STMT_COLUMNS_OF_TABLE], i_set, 
 							      GDA_STATEMENT_MODEL_RANDOM_ACCESS, col_types, error);
 	if (!model)
 		return FALSE;
@@ -379,7 +330,9 @@
 
 	/* modify meta store with @proxy */
 	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, proxy, NULL, error, NULL);
+		retval = gda_meta_store_modify (store, context->table_name, proxy, 
+						"table_schema = ##schema::string AND table_name = ##name::string", error, 
+						"schema", table_schema, "name", table_name, NULL);
 	g_object_unref (proxy);
 	g_object_unref (model);
 
@@ -387,28 +340,10 @@
 }
 
 gboolean
-_gda_postgres_meta_columns_c (GdaServerProvider *prov, GdaConnection *cnc, 
-			      GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-			      const GValue *table_schema, const GValue *table_name, const GValue *column_name)
-{
-	GdaDataModel *model;
-	gboolean retval = TRUE;
-
-	model = gda_meta_store_create_modify_data_model (store, context->table_name);
-	g_assert (model);
-
-	/* fill in @model */
-	TO_IMPLEMENT;
-	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
-	g_object_unref (model);
-
-	return retval;
-}
-
-gboolean
 _gda_postgres_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
-				    GdaMetaStore *store, GdaMetaContext *context, GError **error)
+				    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+				    const GValue *constraint_name_n)
 {
 	GdaDataModel *model;
 	gboolean retval = TRUE;
@@ -418,82 +353,45 @@
 	if (!cdata)
 		return FALSE;
 
-	/* use a prepared statement for the "base" model */
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_ALL_TABLES_CONSTRAINTS], NULL, 
-							 error);
-	if (!model)
-		return FALSE;
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name);
+
+	if (!constraint_name_n) {
+		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES_CONSTRAINTS], i_set, 
+								 error);
+		if (!model)
+			return FALSE;
+		if (retval)
+			retval = gda_meta_store_modify (store, context->table_name, model, 
+							"table_schema = ##schema::string AND table_name = ##name::string", 
+							error, 
+							"schema", table_schema, "name", table_name, NULL);
 
+	}
+	else {
+		gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name_n);
+		model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLES_CONSTRAINT_NAMED], i_set, 
+								 error);
+		if (!model)
+			return FALSE;
+		if (retval)
+			retval = gda_meta_store_modify (store, context->table_name, model, 
+							"table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string", error, 
+							"schema", table_schema, "name", table_name, "name2", constraint_name_n, NULL);
+	}
 
-	/* modify meta store with @proxy */
-	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
 	g_object_unref (model);
 
 	return retval;
 }
 
-gboolean
-_gda_postgres_meta_constraints_tab_s (GdaServerProvider *prov, GdaConnection *cnc, 
-				      GdaMetaStore *store, GdaMetaContext *context, GError **error,
-				      const GValue *table_schema, const GValue *table_name)
-{
-	GdaDataModel *model;
-	gboolean retval = TRUE;
-	PostgresConnectionData *cdata;
-
-	cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
-		return FALSE;
-
-	/* use a prepared statement for the "base" model */
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "schema"), table_schema);
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "tblname"), table_name);
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_TABLE_CONSTRAINTS], pragma_set, 
-							 error);
-	if (!model)
-		return FALSE;
-
-
-	/* modify meta store with @proxy */
-	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
-	g_object_unref (model);
-
-	return retval;
-}
 
 gboolean
 _gda_postgres_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
-				    GdaMetaStore *store, GdaMetaContext *context, GError **error)
-{
-	GdaDataModel *model;
-	gboolean retval = TRUE;
-	PostgresConnectionData *cdata;
-
-	cdata = (PostgresConnectionData*) gda_connection_internal_get_provider_data (cnc);
-	if (!cdata)
-		return FALSE;
-
-	/* use a prepared statement for the "base" model */
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_ALL_REF_CONSTRAINTS], NULL, 
-							 error);
-	if (!model)
-		return FALSE;
-
-
-	/* modify meta store with @proxy */
-	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
-	g_object_unref (model);
-
-	return retval;
-}
-
-gboolean
-_gda_postgres_meta_constraints_ref_c (GdaServerProvider *prov, GdaConnection *cnc, 
-				      GdaMetaStore *store, GdaMetaContext *context, GError **error,
-				      const GValue *constraint_schema, const GValue *constraint_name)
+				    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+				    const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+				    const GValue *constraint_name)
 {
 	GdaDataModel *model;
 	gboolean retval = TRUE;
@@ -503,18 +401,22 @@
 	if (!cdata)
 		return FALSE;
 
-	/* use a prepared statement for the "base" model */
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "schema"), constraint_schema);
-	gda_holder_set_value (gda_set_get_holder (pragma_set, "constname"), constraint_name);
-	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_REF_CONSTRAINTS], pragma_set, 
+	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), table_catalog);
+	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name);
+	gda_holder_set_value (gda_set_get_holder (i_set, "name2"), constraint_name);
+	model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_REF_CONSTRAINTS], i_set, 
 							 error);
 	if (!model)
 		return FALSE;
 
 
-	/* modify meta store with @proxy */
+	/* modify meta store */
 	if (retval)
-		retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
+		retval = gda_meta_store_modify (store, context->table_name, model, 
+						"table_schema = ##schema::string AND table_name = ##name::string AND constraint_name = ##name2::string", 
+						error, 
+						"schema", table_schema, "name", table_name, "name2", constraint_name, NULL);
 	g_object_unref (model);
 
 	return retval;

Modified: trunk/providers/postgres/gda-postgres-meta.h
==============================================================================
--- trunk/providers/postgres/gda-postgres-meta.h	(original)
+++ trunk/providers/postgres/gda-postgres-meta.h	Wed Mar 12 21:18:24 2008
@@ -31,29 +31,18 @@
 					      GdaMetaStore *store, GdaMetaContext *context, GError **error);
 gboolean _gda_postgres_meta_btypes           (GdaServerProvider *prov, GdaConnection *cnc, 
 					      GdaMetaStore *store, GdaMetaContext *context, GError **error);
-gboolean _gda_postgres_meta_schemata         (GdaServerProvider *prov, GdaConnection *cnc, 
-					      GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					      const GValue *schema_name);
-gboolean _gda_postgres_meta_tables_views     (GdaServerProvider *prov, GdaConnection *cnc, 
-					      GdaMetaStore *store, GdaMetaContext *context, GError **error);
-gboolean _gda_postgres_meta_tables_views_s   (GdaServerProvider *prov, GdaConnection *cnc, 
-					      GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					      const GValue *table_schema, const GValue *table_name);
-gboolean _gda_postgres_meta_columns           (GdaServerProvider *prov, GdaConnection *cnc, 
-					       GdaMetaStore *store, GdaMetaContext *context, GError **error);
-gboolean _gda_postgres_meta_columns_t         (GdaServerProvider *prov, GdaConnection *cnc, 
-					       GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					       const GValue *table_schema, const GValue *table_name);
-gboolean _gda_postgres_meta_columns_c         (GdaServerProvider *prov, GdaConnection *cnc, 
-					       GdaMetaStore *store, GdaMetaContext *context, GError **error, 
-					       const GValue *table_schema, const GValue *table_name, const GValue *column_name);
-gboolean _gda_postgres_meta_constraints_tab   (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-gboolean _gda_postgres_meta_constraints_tab_s (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-					       const GValue *table_schema, const GValue *table_name);
-
-gboolean _gda_postgres_meta_constraints_ref   (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **);
-gboolean _gda_postgres_meta_constraints_ref_c (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
-					       const GValue *table_schema, const GValue *table_name);
+gboolean _gda_postgres_meta_schemata         (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **, 
+					      const GValue *catalog_name, const GValue *schema_name_n);
+gboolean _gda_postgres_meta_tables_views     (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name_n);
+gboolean _gda_postgres_meta_columns          (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name);
+gboolean _gda_postgres_meta_constraints_tab  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+					      const GValue *constraint_name_n);
+gboolean _gda_postgres_meta_constraints_ref  (GdaServerProvider *, GdaConnection *, GdaMetaStore *, GdaMetaContext *, GError **,
+					      const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
+					      const GValue *constraint_name);
 
 
 G_END_DECLS

Modified: trunk/providers/postgres/gda-postgres-provider.c
==============================================================================
--- trunk/providers/postgres/gda-postgres-provider.c	(original)
+++ trunk/providers/postgres/gda-postgres-provider.c	Wed Mar 12 21:18:24 2008
@@ -185,18 +185,13 @@
 	provider_class->statement_execute = gda_postgres_provider_statement_execute;
 
 	memset (&(provider_class->meta_funcs), 0, sizeof (GdaServerProviderMeta));
-	provider_class->meta_funcs.info = _gda_postgres_meta_info;
-	provider_class->meta_funcs.btypes = _gda_postgres_meta_btypes;
+	provider_class->meta_funcs._info = _gda_postgres_meta_info;
+	provider_class->meta_funcs._btypes = _gda_postgres_meta_btypes;
 	provider_class->meta_funcs.schemata = _gda_postgres_meta_schemata;
 	provider_class->meta_funcs.tables_views = _gda_postgres_meta_tables_views;
-	provider_class->meta_funcs.tables_views_s = _gda_postgres_meta_tables_views_s;
 	provider_class->meta_funcs.columns = _gda_postgres_meta_columns;
-	provider_class->meta_funcs.columns_t = _gda_postgres_meta_columns_t;
-	provider_class->meta_funcs.columns_c = _gda_postgres_meta_columns_c;
 	provider_class->meta_funcs.constraints_tab = _gda_postgres_meta_constraints_tab;
-	provider_class->meta_funcs.constraints_tab_s = _gda_postgres_meta_constraints_tab_s;
 	provider_class->meta_funcs.constraints_ref = _gda_postgres_meta_constraints_ref;
-	provider_class->meta_funcs.constraints_ref_c = _gda_postgres_meta_constraints_ref_c;
 }
 
 static void

Modified: trunk/providers/sqlite/sqlite_specs_create_table.xml.in
==============================================================================
--- trunk/providers/sqlite/sqlite_specs_create_table.xml.in	(original)
+++ trunk/providers/sqlite/sqlite_specs_create_table.xml.in	Wed Mar 12 21:18:24 2008
@@ -30,14 +30,14 @@
         <gda_array_row>
             <gda_value>id</gda_value>
             <gda_value>integer</gda_value>
-            <gda_value></gda_value>
-            <gda_value></gda_value>
+            <gda_value isnull='t'></gda_value>
+            <gda_value isnull='t'></gda_value>
             <gda_value>FALSE</gda_value>
             <gda_value>TRUE</gda_value>
             <gda_value>FALSE</gda_value>
             <gda_value>TRUE</gda_value>
-            <gda_value></gda_value>
-            <gda_value></gda_value>
+            <gda_value isnull='t'></gda_value>
+            <gda_value isnull='t'></gda_value>
         </gda_array_row>
     </gda_array_data>
   </gda_array>

Modified: trunk/tests/data-models/check_data_proxy.c
==============================================================================
--- trunk/tests/data-models/check_data_proxy.c	(original)
+++ trunk/tests/data-models/check_data_proxy.c	Wed Mar 12 21:18:24 2008
@@ -123,6 +123,10 @@
 	if (!do_test_proxied_model_modif ())
 		number_failed ++;
 
+	if (number_failed == 0)
+		g_print ("Ok.\n");
+	else
+		g_print ("%d failed\n", number_failed);
 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 

Modified: trunk/tests/data-models/check_model_import.c
==============================================================================
--- trunk/tests/data-models/check_model_import.c	(original)
+++ trunk/tests/data-models/check_model_import.c	Wed Mar 12 21:18:24 2008
@@ -48,6 +48,10 @@
 		}
 	g_dir_close (dir);
 
+	if (number_failed == 0)
+		g_print ("Ok.\n");
+	else
+		g_print ("%d failed\n", number_failed);
 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 

Modified: trunk/tests/meta-store/common.c
==============================================================================
--- trunk/tests/meta-store/common.c	(original)
+++ trunk/tests/meta-store/common.c	Wed Mar 12 21:18:24 2008
@@ -15,7 +15,7 @@
 GSList *expected_changes;
 
 static void meta_changed_cb (GdaMetaStore *store, GSList *changes, gpointer data);
-static void suggest_update_cb (GdaMetaStore *store, GdaMetaContext *context, gpointer data);
+static GError *suggest_update_cb (GdaMetaStore *store, GdaMetaContext *context, gpointer data);
 
 /*
  * Declare a GdaMetaStore to test
@@ -91,17 +91,18 @@
 	}
 }
 
-static void
+static GError *
 suggest_update_cb (GdaMetaStore *store, GdaMetaContext *context, gpointer data)
 {
 	gint i;
-	g_print ("Update suggested for table %s:\n", context->table_name);
+	g_print ("test: Update suggested for table %s:\n", context->table_name);
 	for (i = 0; i < context->size; i++) {
 		gchar *str;
 		str = gda_value_stringify (context->column_values[i]);
 		g_print ("\t%s => %s\n", context->column_names[i], str);
 		g_free (str);
 	}
+	return NULL;
 }
 
 /*
@@ -272,11 +273,6 @@
 	};
 	gchar *view_names [] = {
 		"_all_types",
-		"_constraint_column_usage",
-		"_constraint_table_usage",
-		"_view_table_usage",
-		"_check_constraints",
-		"_domain_column_usage"
 	};
 	
 	GdaConnection *cnc = gda_meta_store_get_internal_connection (store);
@@ -346,7 +342,7 @@
 	test_columns (store);
 	test_table_constraints (store);
 	test_referential_constraints (store);
-	test_key_column_usage (store);
+	/*test_key_column_usage (store);*/
 	test_domain_constraints (store);
 	test_parameters (store);
 }

Modified: trunk/tests/providers/Makefile.am
==============================================================================
--- trunk/tests/providers/Makefile.am	(original)
+++ trunk/tests/providers/Makefile.am	Wed Mar 12 21:18:24 2008
@@ -170,22 +170,6 @@
 	PostgreSQL_create_tables.sql \
 	SQLite_create_tables.sql \
 	MySQL_create_tables.sql \
-        FIELDS_SCHEMA_Mdb_actor.xml \
-        FIELDS_SCHEMA_Mdb_film_actor.xml \
-        FIELDS_SCHEMA_Mdb_film.xml \
-        FIELDS_SCHEMA_Mdb_language.xml \
-	FIELDS_SCHEMA_MySQL_actor.xml \
-	FIELDS_SCHEMA_MySQL_film_actor.xml \
-	FIELDS_SCHEMA_MySQL_film.xml \
-	FIELDS_SCHEMA_MySQL_language.xml \
-	FIELDS_SCHEMA_PostgreSQL_actor.xml \
-	FIELDS_SCHEMA_PostgreSQL_film_actor.xml \
-	FIELDS_SCHEMA_PostgreSQL_film.xml \
-	FIELDS_SCHEMA_PostgreSQL_language.xml \
-	FIELDS_SCHEMA_SQLite_actor.xml \
-	FIELDS_SCHEMA_SQLite_film_actor.xml \
-	FIELDS_SCHEMA_SQLite_film.xml \
-	FIELDS_SCHEMA_SQLite_language.xml \
 	TYPES_SCHEMA_Mdb.xml \
 	TYPES_SCHEMA_MySQL.xml \
 	TYPES_SCHEMA_PostgreSQL.xml \

Modified: trunk/tests/providers/README
==============================================================================
--- trunk/tests/providers/README	(original)
+++ trunk/tests/providers/README	Wed Mar 12 21:18:24 2008
@@ -41,10 +41,10 @@
 
 MYSQL_DBCREATE_PARAMS "HOST=localhost"
 POSTGRESQL_DBCREATE_PARAMS "HOST=localhost;PORT=5432"
-SQLITE_DBCREATE_PARAMS "DB_DIR=/home/me/libgda/tests/providers"
-BERKELEY_DB_CNC_PARAMS "FILE=gda_check_bdb.db"
+SQLITE_DBCREATE_PARAMS "DB_DIR=."
+BERKELEY_DB_CNC_PARAMS "DB_NAME=gda_check_bdb.db"
 
 The MDB provider does not allow database creation, so use the gda_check_db.mdb file in this directory
-MS_ACCESS_CNC_PARAMS "DB_DIR=/home/me/libgda/tests/providers;DB_NAME=gda_check_db"
+MSACCESS_CNC_PARAMS "DB_DIR=/home/me/libgda/tests/providers;DB_NAME=gda_check_db"
 
 ORACLE_CNC_PARAMS TNSNAME=//127.0.0.1

Modified: trunk/tests/providers/TYPES_SCHEMA_SQLite.xml
==============================================================================
--- trunk/tests/providers/TYPES_SCHEMA_SQLite.xml	(original)
+++ trunk/tests/providers/TYPES_SCHEMA_SQLite.xml	Wed Mar 12 21:18:24 2008
@@ -1,142 +1,56 @@
 <?xml version="1.0"?>
 <gda_array id="EXPORT" name="Exported Data">
-  <gda_array_field id="FI0" name="Type" title="Type" gdatype="gchararray" nullok="TRUE"/>
-  <gda_array_field id="FI1" name="Owner" title="Owner" gdatype="gchararray" nullok="TRUE"/>
-  <gda_array_field id="FI2" name="Comments" title="Comments" gdatype="gchararray" nullok="TRUE"/>
-  <gda_array_field id="FI3" name="GDA type" title="GDA type" gdatype="gulong" nullok="TRUE"/>
-  <gda_array_field id="FI4" name="Synonyms" title="Synonyms" gdatype="gchararray" nullok="TRUE"/>
+  <gda_array_field id="FI0" name="short_type_name" title="short_type_name" gdatype="gchararray" size="-1" scale="-1"/>
+  <gda_array_field id="FI1" name="gtype" title="gtype" gdatype="gchararray" size="-1" scale="-1" nullok="TRUE"/>
+  <gda_array_field id="FI2" name="comments" title="comments" gdatype="gchararray" size="-1" scale="-1" nullok="TRUE"/>
+  <gda_array_field id="FI3" name="synonyms" title="synonyms" gdatype="gchararray" size="-1" scale="-1" nullok="TRUE"/>
   <gda_array_data>
     <gda_array_row>
-      <gda_value>integer</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value>Signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value</gda_value>
-      <gda_value>24</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>real</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value>Floating point value, stored as an 8-byte IEEE floating point number</gda_value>
-      <gda_value>60</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>text</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value>Text string, stored using the database encoding</gda_value>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
       <gda_value>blob</gda_value>
-      <gda_value>system</gda_value>
+      <gda_value>GdaBinary</gda_value>
       <gda_value>Blob of data, stored exactly as it was input</gda_value>
-      <gda_value>145570992</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>timestamp</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value>Time stamp, stored as 'YYYY-MM-DD HH:MM:SS.SSS'</gda_value>
-      <gda_value>145573576</gda_value>
       <gda_value isnull="t"/>
     </gda_array_row>
     <gda_array_row>
-      <gda_value>time</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value>Time, stored as 'HH:MM:SS.SSS'</gda_value>
-      <gda_value>145568736</gda_value>
-      <gda_value isnull="t"/>
+      <gda_value>boolean</gda_value>
+      <gda_value>gboolean</gda_value>
+      <gda_value>Boolean value</gda_value>
+      <gda_value>bool</gda_value>
     </gda_array_row>
     <gda_array_row>
       <gda_value>date</gda_value>
-      <gda_value>system</gda_value>
+      <gda_value>GDate</gda_value>
       <gda_value>Date, stored as 'YYYY-MM-DD'</gda_value>
-      <gda_value>145570864</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>VARCHAR(45)</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>INTEGER</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>24</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>CHAR(20)</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>SMALLINT</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>24</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>VARCHAR</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>year</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
-    </gda_array_row>
-    <gda_array_row>
-      <gda_value>TEXT[]</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
       <gda_value isnull="t"/>
     </gda_array_row>
     <gda_array_row>
-      <gda_value>VARCHAR(255)</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
+      <gda_value>integer</gda_value>
+      <gda_value>gint</gda_value>
+      <gda_value>Signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value</gda_value>
+      <gda_value>int</gda_value>
     </gda_array_row>
     <gda_array_row>
-      <gda_value>TEXT</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
+      <gda_value>real</gda_value>
+      <gda_value>gdouble</gda_value>
+      <gda_value>Floating point value, stored as an 8-byte IEEE floating point number</gda_value>
       <gda_value isnull="t"/>
     </gda_array_row>
     <gda_array_row>
-      <gda_value>NUMERIC(4,2)</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
-      <gda_value isnull="t"/>
+      <gda_value>text</gda_value>
+      <gda_value>string</gda_value>
+      <gda_value>Text string, stored using the database encoding</gda_value>
+      <gda_value>string</gda_value>
     </gda_array_row>
     <gda_array_row>
-      <gda_value>TIMESTAMP</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
+      <gda_value>time</gda_value>
+      <gda_value>GdaTime</gda_value>
+      <gda_value>Time, stored as 'HH:MM:SS.SSS'</gda_value>
       <gda_value isnull="t"/>
     </gda_array_row>
     <gda_array_row>
-      <gda_value>NUMERIC(5,2)</gda_value>
-      <gda_value>system</gda_value>
-      <gda_value isnull="t"/>
-      <gda_value>64</gda_value>
+      <gda_value>timestamp</gda_value>
+      <gda_value>GdaTimestamp</gda_value>
+      <gda_value>Time stamp, stored as 'YYYY-MM-DD HH:MM:SS.SSS'</gda_value>
       <gda_value isnull="t"/>
     </gda_array_row>
   </gda_array_data>

Modified: trunk/tests/providers/check_bdb.c
==============================================================================
--- trunk/tests/providers/check_bdb.c	(original)
+++ trunk/tests/providers/check_bdb.c	Wed Mar 12 21:18:24 2008
@@ -26,13 +26,15 @@
 	number_failed = prov_test_common_setup ();
 
 	if (cnc) {
-		number_failed += prov_test_check_table_schema (cnc, "data");
+		number_failed += prov_test_common_check_meta ();
 		number_failed += prov_test_common_clean ();
 	}
 
 	if (! params_provided)
 		return EXIT_SUCCESS;
-	else
+	else {
+		g_print ("Test %s\n", (number_failed == 0) ? "Ok" : "failed");
 		return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+	}
 }
 

Modified: trunk/tests/providers/check_mdb.c
==============================================================================
--- trunk/tests/providers/check_mdb.c	(original)
+++ trunk/tests/providers/check_mdb.c	Wed Mar 12 21:18:24 2008
@@ -27,13 +27,15 @@
 
 	if (cnc) {
 		/* don't test create tables because it does not work for that provider */
-		number_failed += prov_test_common_check_schemas ();
+		number_failed += prov_test_common_check_meta ();
 		number_failed += prov_test_common_clean ();
 	}
 
 	if (! params_provided)
 		return EXIT_SUCCESS;
-	else
+	else {
+		g_print ("Test %s\n", (number_failed == 0) ? "Ok" : "failed");
 		return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+	}
 }
 

Modified: trunk/tests/providers/check_mysql.c
==============================================================================
--- trunk/tests/providers/check_mysql.c	(original)
+++ trunk/tests/providers/check_mysql.c	Wed Mar 12 21:18:24 2008
@@ -27,13 +27,15 @@
 
 	if (cnc) {
 		number_failed += prov_test_common_create_tables_sql ();
-		number_failed += prov_test_common_check_schemas ();
+		number_failed += prov_test_common_check_meta ();
 		number_failed += prov_test_common_clean ();
 	}
 
 	if (! params_provided)
 		return EXIT_SUCCESS;
-	else
+	else {
+		g_print ("Test %s\n", (number_failed == 0) ? "Ok" : "failed");
 		return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+	}
 }
 

Modified: trunk/tests/providers/check_oracle.c
==============================================================================
--- trunk/tests/providers/check_oracle.c	(original)
+++ trunk/tests/providers/check_oracle.c	Wed Mar 12 21:18:24 2008
@@ -27,13 +27,15 @@
 
 	if (cnc) {
 		number_failed += prov_test_common_create_tables_sql ();
-		number_failed += prov_test_common_check_schemas ();
+		number_failed += prov_test_common_check_meta ();
 		number_failed += prov_test_common_clean ();
 	}
 
 	if (! params_provided)
 		return EXIT_SUCCESS;
-	else
+	else {
+		g_print ("Test %s\n", (number_failed == 0) ? "Ok" : "failed");
 		return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+	}
 }
 

Modified: trunk/tests/providers/check_postgres.c
==============================================================================
--- trunk/tests/providers/check_postgres.c	(original)
+++ trunk/tests/providers/check_postgres.c	Wed Mar 12 21:18:24 2008
@@ -29,7 +29,7 @@
 
 	if (cnc) {
 		number_failed += prov_test_common_create_tables_sql ();
-		number_failed += prov_test_common_check_schemas ();
+		number_failed += prov_test_common_check_meta ();
 		number_failed += prov_test_common_load_data ();
 		number_failed += prov_test_common_check_cursor_models ();
 		number_failed += prov_test_common_clean ();
@@ -37,7 +37,9 @@
 
 	if (! params_provided)
 		return EXIT_SUCCESS;
-	else
+	else {
+		g_print ("Test %s\n", (number_failed == 0) ? "Ok" : "failed");
 		return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+	}
 }
 

Modified: trunk/tests/providers/check_sqlite.c
==============================================================================
--- trunk/tests/providers/check_sqlite.c	(original)
+++ trunk/tests/providers/check_sqlite.c	Wed Mar 12 21:18:24 2008
@@ -29,7 +29,7 @@
 
 	if (cnc) {
 		number_failed += prov_test_common_create_tables_sql ();
-		number_failed += prov_test_common_check_schemas ();
+		number_failed += prov_test_common_check_meta ();
 		number_failed += prov_test_common_load_data ();
 		number_failed += prov_test_common_check_cursor_models ();
 		number_failed += prov_test_common_clean ();
@@ -37,7 +37,9 @@
 
 	if (! params_provided)
 		return EXIT_SUCCESS;
-	else
+	else {
+		g_print ("Test %s\n", (number_failed == 0) ? "Ok" : "failed");
 		return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+	}
 }
 

Modified: trunk/tests/providers/prov-test-common.c
==============================================================================
--- trunk/tests/providers/prov-test-common.c	(original)
+++ trunk/tests/providers/prov-test-common.c	Wed Mar 12 21:18:24 2008
@@ -2,6 +2,10 @@
 #include <string.h>
 #include "prov-test-common.h"
 #include "prov-test-util.h"
+#include <sql-parser/gda-sql-statement.h>
+
+#define CHECK_EXTRA_INFO
+/*#undef CHECK_EXTRA_INFO*/
 
 GdaProviderInfo *pinfo;
 GdaConnection   *cnc;
@@ -59,24 +63,131 @@
 
 /*
  *
- * CHECK_SCHEMAS
+ * CHECK_META
  *
  */
 
 int
-prov_test_common_check_schemas ()
+prov_test_common_check_meta ()
 {
 	int number_failed = 0;
-	if (!prov_test_check_table_schema (cnc, "actor"))
-		number_failed++;
-	if (!prov_test_check_table_schema (cnc, "language"))
-		number_failed++;
-	if (!prov_test_check_table_schema (cnc, "film"))
-		number_failed++;
-	if (!prov_test_check_table_schema (cnc, "film_actor"))
-		number_failed++;
-	if (!prov_test_check_types_schema (cnc))
-		number_failed++;
+	GSList *tables, *list;
+	gboolean dump_ok = TRUE;
+	GdaMetaStore *store;
+	gchar **dump1 = NULL;
+	GError *gerror = NULL;
+	gint ntables, i;
+
+	/* update meta store */
+	if (! gda_connection_update_meta_store (cnc, NULL, &gerror)) {
+#ifdef CHECK_EXTRA_INFO
+		g_warning ("Can't update meta store (1): %s\n",
+			   gerror && gerror->message ? gerror->message : "???");
+#endif
+		g_error_free (gerror);
+		number_failed++;
+		goto theend;
+	}
+
+	/* dump all tables */
+	store = gda_connection_get_meta_store (cnc);
+	tables = gda_meta_store_schema_get_tables (store);
+	ntables = g_slist_length (tables);
+	dump1 = g_new0 (gchar *, ntables + 1);
+
+	for (i = 0, list = tables; list; i++, list = list->next) {
+		GdaDataModel *model;
+		gchar *tmp;
+		
+		tmp = g_strdup_printf ("SELECT * FROM %s", (gchar*) list->data);
+		model = gda_meta_store_extract (store, tmp, &gerror, NULL);
+		g_free (tmp);
+		if (!model) {
+#ifdef CHECK_EXTRA_INFO
+			g_warning ("Can't execute SELECT statement: %s\n",
+				   gerror && gerror->message ? gerror->message : "???");
+#endif
+			g_error_free (gerror);
+			dump_ok = FALSE;
+			break;
+		}
+
+		dump1 [i] = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML,
+							     NULL, 0, NULL, 0, NULL);
+		g_object_unref (model);
+		if (!dump1 [i]) {
+#ifdef CHECK_EXTRA_INFO
+			g_warning ("Can't export data model\n");
+#endif
+			dump_ok = FALSE;
+			break;
+		}
+	}
+
+	if (!dump_ok) {
+		number_failed++;
+		goto theend;
+	}
+
+	/* update meta store */
+	if (! gda_connection_update_meta_store (cnc, NULL, &gerror)) {
+#ifdef CHECK_EXTRA_INFO
+		g_warning ("Can't update meta store (2): %s\n",
+			   gerror && gerror->message ? gerror->message : "???");
+#endif
+		g_error_free (gerror);
+		number_failed++;
+		goto theend;
+	}
+
+	for (i = 0, list = tables; list; i++, list = list->next) {
+		GdaDataModel *model;
+		gchar *tmp;
+		GError *gerror = NULL;
+		
+		tmp = g_strdup_printf ("SELECT * FROM %s", (gchar*) list->data);
+		model = gda_meta_store_extract (store, tmp, &gerror, NULL);
+		g_free (tmp);
+		if (!model) {
+#ifdef CHECK_EXTRA_INFO
+			g_warning ("Can't execute SELECT statement: %s\n",
+				   gerror && gerror->message ? gerror->message : "???");
+#endif
+			g_error_free (gerror);
+			number_failed++;
+			continue;
+		}
+
+		tmp = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML,
+						       NULL, 0, NULL, 0, NULL);
+		g_object_unref (model);
+		if (!tmp) {
+#ifdef CHECK_EXTRA_INFO
+			g_warning ("Can't export data model\n");
+#endif
+			number_failed++;
+			continue;
+		}
+		if (strcmp (tmp, dump1[i])) {
+#ifdef CHECK_EXTRA_INFO
+			g_warning ("Meta data has changed after update for table %s\n", (gchar*) list->data);
+#endif
+			number_failed++;
+			g_free (tmp);
+			continue;
+		}
+#ifdef CHECK_EXTRA_INFO
+		else
+			g_print ("Meta for table '%s' Ok\n", (gchar*) list->data);
+#endif
+		g_free (tmp);
+	}
+
+ theend:
+	/* remove tmp files */
+	if (dump1)
+		g_strfreev (dump1);
+	g_slist_free (tables);
 
 	return number_failed;	
 }

Modified: trunk/tests/providers/prov-test-common.h
==============================================================================
--- trunk/tests/providers/prov-test-common.h	(original)
+++ trunk/tests/providers/prov-test-common.h	Wed Mar 12 21:18:24 2008
@@ -13,7 +13,7 @@
 int prov_test_common_setup ();
 int prov_test_common_create_tables_sql ();
 int prov_test_common_load_data ();
-int prov_test_common_check_schemas ();
+int prov_test_common_check_meta ();
 int prov_test_common_check_cursor_models ();
 int prov_test_common_clean ();
 

Modified: trunk/tests/providers/prov-test-util.c
==============================================================================
--- trunk/tests/providers/prov-test-util.c	(original)
+++ trunk/tests/providers/prov-test-util.c	Wed Mar 12 21:18:24 2008
@@ -10,7 +10,7 @@
 /*#undef CHECK_EXTRA_INFO*/
 
 #define DB_NAME "gda_check_db"
-#define CREATE_FILES 0
+#define CREATE_FILES 1
 GdaSqlParser *parser = NULL;
 
 /*
@@ -175,14 +175,14 @@
 
 		db_name = DB_NAME;
 		db_quark_list = gda_quark_list_new_from_string (db_params);
-		op = gda_prepare_drop_database (client, db_name, prov_info->id);
+		op = gda_prepare_drop_database (prov_info->id, db_name, NULL);
 		gda_quark_list_foreach (db_quark_list, (GHFunc) db_create_quark_foreach_func, op);
-		gda_perform_create_database (client, op, NULL);
+		gda_perform_create_database (op, NULL);
 		g_object_unref (op);
 
-		op = gda_prepare_create_database (client, db_name, prov_info->id);
+		op = gda_prepare_create_database (prov_info->id, db_name, NULL);
 		gda_quark_list_foreach (db_quark_list, (GHFunc) db_create_quark_foreach_func, op);
-		if (!gda_perform_create_database (client, op, &error)) {
+		if (!gda_perform_create_database (op, &error)) {
 #ifdef CHECK_EXTRA_INFO
 			g_warning ("Could not create the '%s' database (provider %s): %s", db_name,
 				   prov_info->id, error && error->message ? error->message : "No detail");
@@ -219,15 +219,23 @@
 		g_print ("Open connection string: %s\n", data.string->str);
 
 		const gchar *username, *password;
+		gchar *auth = NULL;
 		str = g_strdup_printf ("%s_USER", upname);
 		username = getenv (str);
 		g_free (str);
 		str = g_strdup_printf ("%s_PASS", upname);
 		password = getenv (str);
 		g_free (str);
+		if (username) {
+			if (password)
+				auth = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", username, password);
+			else
+				auth = g_strdup_printf ("USERNAME=%s", username);
+		}
 
-		cnc = gda_connection_open_from_string (prov_info->id, data.string->str, username, password, 
+		cnc = gda_connection_open_from_string (prov_info->id, data.string->str, auth, 
 						       GDA_CONNECTION_OPTIONS_NONE, &error);
+		g_free (auth);
 		if (!cnc && error) {
 #ifdef CHECK_EXTRA_INFO
 			g_warning ("Could not open connection to %s (provider %s): %s",
@@ -304,12 +312,12 @@
 		g_free (str);
 		g_assert (db_params);
 
-		op = gda_prepare_drop_database (client, DB_NAME, prov_id);
+		op = gda_prepare_drop_database (prov_id, DB_NAME, NULL);
 		db_quark_list = gda_quark_list_new_from_string (db_params);
 		gda_quark_list_foreach (db_quark_list, (GHFunc) db_drop_quark_foreach_func, op);
 		gda_quark_list_free (db_quark_list);
 
-		if (!gda_perform_drop_database (client, op, &error)) {
+		if (!gda_perform_drop_database (op, &error)) {
 #ifdef CHECK_EXTRA_INFO
 			g_warning ("Could not drop the '%s' database (provider %s): %s", DB_NAME,
 				   prov_id, error && error->message ? error->message : "No detail");
@@ -381,68 +389,6 @@
 
 /*
  * 
- * Check a table's schema
- *
- */
-gboolean
-prov_test_check_table_schema (GdaConnection *cnc, const gchar *table)
-{
-	if (!cnc || !gda_connection_is_opened (cnc)) {
-#ifdef CHECK_EXTRA_INFO
-		g_warning ("Connection is closed!");
-#endif
-		return FALSE;
-	}
-
-	GdaServerProvider *prov;
-	GdaDataModel *schema_m;
-	GError *error = NULL;
-	gchar *str;
-	GValue *v;
-	
-	prov = gda_connection_get_provider_obj (cnc);
-	g_value_set_string (v = gda_value_new (G_TYPE_STRING), table);
-	schema_m = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_FIELDS, &error, 1, "name", v);
-	gda_value_free (v);
-	if (!schema_m) {
-#ifdef CHECK_EXTRA_INFO
-		g_warning ("Could not get FIELDS schema for table '%s': %s", table,
-			   error && error->message ? error->message : "No detail");
-#endif
-		return FALSE;
-	}
-
-	str = g_strdup_printf ("FIELDS_SCHEMA_%s_%s.xml", gda_connection_get_provider_name (cnc), table);
-	if (CREATE_FILES) {
-		GdaSet *plist;
-		/* export schema model to a file, to create first version of the files, not to be used in actual checks */
-		plist = gda_set_new_inline (1, "OVERWRITE", G_TYPE_BOOLEAN, TRUE);
-		if (! (gda_data_model_export_to_file (schema_m, GDA_DATA_MODEL_IO_DATA_ARRAY_XML, str, 
-						      NULL, 0, NULL, 0, plist, &error))) {
-#ifdef CHECK_EXTRA_INFO
-			g_warning ("Could not export schema to file '%s': %s", str,
-				   error && error->message ? error->message : "No detail");
-#endif
-			return FALSE;
-		}
-		g_object_unref (plist);
-	}
-	else {
-		/* compare schema with what's expected */
-		gchar *file = g_build_filename (CHECK_SQL_FILES, "tests", "providers", str, NULL);
-		if (!compare_data_model_with_expected (schema_m, file))
-			return FALSE;
-		g_free (file);
-	}
-	g_free (str);
-
-	/*gda_data_model_dump (schema_m, stdout);*/
-	g_object_unref (schema_m);
-	return TRUE;
-}
-
-/*
- * 
  * Check data types' schema
  *
  */
@@ -711,6 +657,11 @@
 		return FALSE;
 	}
 	
+	/* try to start a transaction to spped things up */
+	gboolean started_transaction;
+	started_transaction = gda_connection_begin_transaction (cnc, NULL,
+								GDA_TRANSACTION_ISOLATION_UNKNOWN,
+								NULL);
 	gint row, nrows;
 	nrows = gda_data_model_get_n_rows (imodel);
 	for (row = 0; row < nrows; row++) {
@@ -742,6 +693,10 @@
 			return FALSE;
 		}
 	}
+
+	if (started_transaction) 
+		gda_connection_commit_transaction (cnc, NULL, NULL);
+
 #ifdef CHECK_EXTRA_INFO
 	g_print ("Loaded %d rows into table '%s'\n", nrows, table);
 #endif

Modified: trunk/tests/providers/prov-test-util.h
==============================================================================
--- trunk/tests/providers/prov-test-util.h	(original)
+++ trunk/tests/providers/prov-test-util.h	Wed Mar 12 21:18:24 2008
@@ -16,7 +16,6 @@
 gboolean       prov_test_clean_connection (GdaConnection *cnc, gboolean destroy_db);
 gboolean       prov_test_create_tables_sql (GdaConnection *cnc);
 
-gboolean       prov_test_check_table_schema (GdaConnection *cnc, const gchar *table);
 gboolean       prov_test_check_types_schema (GdaConnection *cnc);
 
 gboolean       prov_test_load_data (GdaConnection *cnc, const gchar *table);

Modified: trunk/tools/command-exec.c
==============================================================================
--- trunk/tools/command-exec.c	(original)
+++ trunk/tools/command-exec.c	Wed Mar 12 21:18:24 2008
@@ -519,7 +519,7 @@
 	GdaMetaStore *store;
 
 	store = gda_connection_get_meta_store (cnc);
-	mstruct = gda_meta_struct_new ();
+	mstruct = gda_meta_struct_new (GDA_META_STRUCT_FEATURE_ALL);
 
 	if (!args[0]) {
 		/* use all tables or views */
@@ -579,8 +579,41 @@
 		}
 		else {
 			/* try to find it as a table or view */
-			if (!gda_meta_struct_complement (mstruct, store, GDA_META_DB_TABLE, NULL, NULL, v, NULL))
-				gda_meta_struct_complement (mstruct, store, GDA_META_DB_VIEW, NULL, NULL, v, NULL);
+			if (!gda_meta_struct_complement (mstruct, store, GDA_META_DB_UNKNOWN, NULL, NULL, v, NULL)) {
+				if (g_str_has_suffix (arg, "=") && (*arg != '=')) {
+					GdaMetaDbObject *dbo;
+					gchar *str;
+					str = g_strdup (arg);
+					str[strlen (str) - 1] = 0;
+					g_value_take_string (v, str);
+					dbo = gda_meta_struct_complement (mstruct, store, GDA_META_DB_TABLE, 
+									  NULL, NULL, v, NULL);
+					if (!dbo)
+						dbo = gda_meta_struct_complement (mstruct, store, GDA_META_DB_VIEW, 
+										  NULL, NULL, v, NULL);
+					if (dbo && dbo->depend_list) {
+						GSList *list, *dep_list;
+						GValue *catalog, *schema, *name;
+
+						dep_list = g_slist_copy (dbo->depend_list);
+						for (list = dep_list; list; list = list->next) {
+							dbo = GDA_META_DB_OBJECT (list->data);
+							g_value_set_string ((catalog = gda_value_new (G_TYPE_STRING)), 
+									    dbo->obj_catalog);
+							g_value_set_string ((schema = gda_value_new (G_TYPE_STRING)), 
+									    dbo->obj_schema);
+							g_value_set_string ((name = gda_value_new (G_TYPE_STRING)), 
+									    dbo->obj_name);
+							gda_meta_struct_complement (mstruct, store, dbo->obj_type,
+										    catalog, schema, name, NULL);
+							gda_value_free (catalog);
+							gda_value_free (schema);
+							gda_value_free (name);
+						}
+						g_slist_free (dep_list);
+					}
+				}
+			}
 		}
 	}
 
@@ -628,8 +661,16 @@
 	if (!mstruct)
 		return NULL;
 
+	/* compute the number of known database objects */
+	gint nb_objects = 0;
+	for (dbo_list = mstruct->db_objects; dbo_list; dbo_list = dbo_list->next) {
+		GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (dbo_list->data);
+		if (dbo->obj_type != GDA_META_DB_UNKNOWN)
+			nb_objects++;
+	}
+
 	/* if more than one object, then show a list */
-	if (mstruct->db_objects && mstruct->db_objects->next) {
+	if (nb_objects > 1) {
 		model = gda_data_model_array_new (4);
 		gda_data_model_set_column_title (model, 0, _("Schema"));
 		gda_data_model_set_column_title (model, 1, _("Name"));

Modified: trunk/tools/gda-sql.c
==============================================================================
--- trunk/tools/gda-sql.c	(original)
+++ trunk/tools/gda-sql.c	Wed Mar 12 21:18:24 2008
@@ -915,6 +915,7 @@
 				if (!data->output_stream) 
 					g_print (_(" Done.\n"));
 		}
+
 		g_object_unref (store);
 	}
 
@@ -2365,81 +2366,15 @@
 create_graph_from_meta_struct (GdaConnection *cnc, GdaMetaStruct *mstruct, GError **error)
 {
 #define FNAME "graph.dot"
-	GString *string;
-	gint i;
-
-	/* prepare the graph */
-	string = g_string_new ("digraph G {\nrankdir = BT;\nnode [shape = plaintext];\n");
-	GSList *dbo_list;
-	for (dbo_list = mstruct->db_objects; dbo_list; dbo_list = dbo_list->next) {
-		gchar *objname, *fullname;
-		GdaMetaDbObject *dbo = GDA_META_DB_OBJECT (dbo_list->data);
-		GSList *list;
-
-		/* obj human readable name, and full name */
-		fullname = g_strdup_printf ("%s.%s.%s", dbo->obj_catalog, dbo->obj_schema, dbo->obj_name);
-		if (dbo->obj_short_name) 
-			objname = g_strdup (dbo->obj_short_name);
-		else
-			objname = g_strdup_printf ("%s.%s", dbo->obj_schema, dbo->obj_name);
-
-		/* node */
-		switch (dbo->obj_type) {
-		case GDA_META_DB_UNKNOWN:
-			break;
-		case GDA_META_DB_TABLE:
-			g_string_append_printf (string, "\"%s\" [label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname);
-			g_string_append_printf (string, "<TR><TD COLSPAN=\"2\" BGCOLOR=\"grey\" BORDER=\"1\">%s</TD></TR>", objname);
-			break;
-		case GDA_META_DB_VIEW:
-			g_string_append_printf (string, "\"%s\" [label=<<TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\">", fullname);
-			g_string_append_printf (string, "<TR><TD BGCOLOR=\"yellow\" BORDER=\"1\">%s</TD></TR>", objname);
-			break;
-		default:
-			TO_IMPLEMENT;
-			g_string_append_printf (string, "\"%s\" [ shape = note ", fullname);
-			break;
-		}
+	gchar *graph;
 
-		/* columns, only for tables */
-		if (dbo->obj_type == GDA_META_DB_TABLE) {
-			GdaMetaTable *mt = GDA_META_DB_OBJECT_GET_TABLE (dbo);
-			for (list = mt->columns; list; list = list->next) {
-				GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
-				GString *extra = g_string_new ("");
-				if (tcol->pkey)
-					g_string_append_printf (extra, "key");
-				g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD><TD ALIGN=\"right\">%s</TD></TR>", 
-							tcol->column_name, extra->str);
-				g_string_free (extra, TRUE);
-			}
-			g_string_append (string, "</TABLE>>];\n");
-			/* foreign keys */
-			for (i = 1, list = mt->fk_list; list; i++, list = list->next) {
-				GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (list->data);
-				if (tfk->depend_on->obj_type != GDA_META_DB_UNKNOWN) 
-					g_string_append_printf (string, "\"%s\" -> \"%s.%s.%s\" [label=\"(%d)\"];\n", fullname,
-								tfk->depend_on->obj_catalog, tfk->depend_on->obj_schema, 
-								tfk->depend_on->obj_name, i);
-			}
-		}
-		else if (dbo->obj_type == GDA_META_DB_VIEW) {
-			GdaMetaTable *mt = GDA_META_DB_OBJECT_GET_TABLE (dbo);
-			for (list = mt->columns; list; list = list->next) {
-				GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
-				g_string_append_printf (string, "<TR><TD ALIGN=\"left\">%s</TD></TR>", tcol->column_name);
-			}
-			g_string_append (string, "</TABLE>>];\n");
-		}
-
-		g_free (objname);
-		g_free (fullname);
-	}
-	g_string_append_c (string, '}');
+	graph = gda_meta_struct_dump_as_graph (mstruct, GDA_META_GRAPH_COLUMNS, error);
+	if (!graph)
+		return NULL;
 
 	/* do something with the graph */
 	gchar *result = NULL;
-	if (g_file_set_contents (FNAME, string->str, -1, error)) {
+	if (g_file_set_contents (FNAME, graph, -1, error)) {
 		const gchar *viewer;
 		const gchar *format;
 		
@@ -2494,7 +2429,7 @@
 						    "Note: set the GDA_SQL_VIEWER_PNG or GDA_SQL_VIEWER_PDF environment "
 						    "variables to view the graph"), FNAME, FNAME);
 	}
-	g_string_free (string, TRUE);
+	g_free (graph);
 	return result;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]