1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
|
------------------------------------------------------------------------------
-- G N A T C O L L --
-- --
-- Copyright (C) 2005-2018, AdaCore --
-- --
-- This library is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- --
-- --
-- --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
pragma Ada_2012;
with Ada.Calendar;
with Ada.Containers.Vectors;
with Ada.Containers.Indefinite_Vectors;
with Ada.Containers.Indefinite_Hashed_Sets;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with GNATCOLL.Refcount; use GNATCOLL.Refcount;
package GNATCOLL.SQL_Impl is
-- Work around issue with the Ada containers: the tampering checks
-- mean that the container might be corrupted if used from multiple
-- tasks, even in read-only.
-- pragma Suppress (Tampering_Check);
type Cst_String_Access is access constant String;
-- Various aspects of a database description (table names, field names,...)
-- are represented as string. To limit the number of memory allocation and
-- deallocation (and therefore increase speed), this package uses such
-- strings as Cst_String_Access. These strings are never deallocation, and
-- should therefore be pointed to "aliased constant String" in your
-- code, as in:
-- Name : aliased constant String := "mysubquery";
-- Q : SQL_Query := SQL_Select
-- (Fields => ...,
-- From => Subquery (SQL_Select (...),
-- Name => Name'Access));
Null_String : aliased constant String := "NULL";
K_Delta : constant := 0.01;
K_Decimals : constant := 2; -- must match K_Delta above
K_Digits : constant := 14;
type T_Money is delta K_Delta digits K_Digits;
-- The base type to represent money in a database. The exact mapping
-- depends on the DBMS (for postgreSQL, this is "numeric(14,2)").
---------------
-- Formatter --
---------------
type Formatter is abstract tagged null record;
-- A formatter provides DBMS-specific formatting for SQL statements.
-- Each backend has its peculiarities, and these are handled through
-- various instances of Formatter.
function Boolean_Image (Self : Formatter; Value : Boolean) return String;
function Money_Image (Self : Formatter; Value : T_Money) return String;
-- Return an image of the various basic types suitable for the DBMS.
-- For instance, sqlite does not support boolean fields, which are thus
-- mapped to integers at the lowest level, even though the Ada layer still
-- manipulates Booleans.
-- If you override these, you will likely want to also override
-- Boolean_Value (DBMS_Forward_Cursor).
function String_Image
(Self : Formatter; Value : String; Quote : Boolean) return String;
-- Escape every apostrophe character "'".
-- Useful for strings in SQL commands where "'" means the end
-- of the current string.
-- This is not suitable for use for prepared queries, which should not be
-- quoted.
-- If Quote is False, Value is returned as is (suitable for prepared
-- queries). Otherwise, Value is surrounded by quote characters, and every
-- special character in Value are also protected.
function Field_Type_Autoincrement
(Self : Formatter) return String is abstract;
-- Return the SQL type to use for auto-incremented fields.
-- Such a field is always a primary key, so this information is also
-- returend as part of the type (this is mandatory for sqlite in
-- particular).
function Field_Type_Money
(Self : Formatter) return String is abstract;
-- Return the SQL type to use for money fields depending on DBMS
function Supports_Timezone (Self : Formatter) return Boolean;
-- Whether the formatter supports time zones for times. Default is True.
function Parameter_String
(Self : Formatter;
Index : Positive;
Type_Descr : String) return String;
-- Return the character to put before a parameter in a SQL statement, when
-- the value will be substituted at run time.
-- Typ describes the type of the parameter, and is returned by the
-- SQL_Parameter primitive operation Describe_Type;
generic
type Base_Type is digits <>;
function Any_Float_To_SQL
(Self : Formatter'Class; Value : Base_Type; Quote : Boolean)
return String;
function Boolean_To_SQL
(Self : Formatter'Class; Value : Boolean; Quote : Boolean) return String;
function Integer_To_SQL
(Self : Formatter'Class; Value : Integer; Quote : Boolean) return String;
function Bigint_To_SQL
(Self : Formatter'Class;
Value : Long_Long_Integer;
Quote : Boolean) return String;
function String_To_SQL
(Self : Formatter'Class; Value : String; Quote : Boolean) return String;
function Time_To_SQL
(Self : Formatter'Class; Value : Ada.Calendar.Time; Quote : Boolean)
return String;
function Date_To_SQL
(Self : Formatter'Class; Value : Ada.Calendar.Time; Quote : Boolean)
return String;
function Money_To_SQL
(Self : Formatter'Class; Value : T_Money; Quote : Boolean) return String;
-- Calls the above formatting primitives (or provide default version, when
-- not overridable)
-- If Quote is False, these functions provide quotes around the values. For
-- instance, the image for a string contains the string itself, unquoted,
-- and with special characters unprotected. As a result, this is only
-- suitable for use with parameterized queries.
----------------
-- Parameters --
----------------
-- Support for parameters when executing SQL queries.
-- See GNATCOLL.SQL.Exec
type SQL_Parameter_Type is abstract tagged null record;
procedure Free (Self : in out SQL_Parameter_Type) is null;
-- Free memory used by Self
function Type_String
(Self : SQL_Parameter_Type;
Index : Positive;
Format : Formatter'Class) return String is abstract;
-- Return the string to use in a query to describe the parameter, for
-- instance "$1::integer" with postgreSQL, or "?1" with sqlite.
-- In general, this will be done via a call to Format.Parameter_String
-- unless you do not need to support multiple DBMS.
function Internal_Image
(Self : SQL_Parameter_Type;
Format : Formatter'Class) return String with Inline;
-- Marshall the parameter to a string, to pass it to the DBMS.
-- Use the formatter's primitives to encode basic types when possible.
procedure Free_Dispatch (Self : in out SQL_Parameter_Type'Class);
package Parameters is new GNATCOLL.Refcount.Shared_Pointers
(SQL_Parameter_Type'Class, Free_Dispatch);
type SQL_Parameter_Base is new Parameters.Ref with null record;
function Image
(Self : SQL_Parameter_Base;
Format : Formatter'Class) return String
is (if Self.Is_Null then "NULL" else Internal_Image (Self.Get, Format));
-- Marshall the parameter to a string, to pass it to the DBMS.
-- Null parameter show as NULL to avoid Constraint_Error.
generic
type Ada_Type is private;
SQL_Type : String;
with function Image
(Format : Formatter'Class; Value : Ada_Type; Quote : Boolean)
return String;
package Scalar_Parameters is
-- A helper package to create simple sql parameters. These assume
-- the data type is constrained, and that they map to a single SQL
-- type.
type SQL_Parameter is new SQL_Parameter_Type with record
Val : Ada_Type;
end record;
overriding function Type_String
(Self : SQL_Parameter;
Index : Positive;
Format : Formatter'Class) return String
is (Format.Parameter_String (Index, SQL_Type));
overriding function Internal_Image
(Self : SQL_Parameter;
Format : Formatter'Class) return String
is (Image (Format, Self.Val, Quote => False));
end Scalar_Parameters;
----------------------
-- Parameters types --
----------------------
type SQL_Parameter_Text is new SQL_Parameter_Type with record
Str_Ptr : access constant String;
-- References external string, to avoid an extra copy
Str_Val : Unbounded_String;
-- Unbounded string copies only reference on assignment
Make_Copy : Boolean;
-- If set this forces SQL engine to make a copy of Str_Ptr.all
end record;
function To_String (Self : SQL_Parameter_Text) return String
is (if Self.Str_Ptr = null
then To_String (Self.Str_Val)
else Self.Str_Ptr.all);
overriding function Type_String
(Self : SQL_Parameter_Text;
Index : Positive;
Format : Formatter'Class) return String
is (Format.Parameter_String (Index, "text"));
overriding function Internal_Image
(Self : SQL_Parameter_Text;
Format : Formatter'Class) return String with Inline;
type SQL_Parameter_Character is new SQL_Parameter_Type with record
Char_Val : Character;
end record;
overriding function Type_String
(Self : SQL_Parameter_Character;
Index : Positive;
Format : Formatter'Class) return String
is (Format.Parameter_String (Index, "text"));
overriding function Internal_Image
(Self : SQL_Parameter_Character;
Format : Formatter'Class) return String with Inline;
-------------------------------------
-- General declarations for tables --
-------------------------------------
-- The following declarations are needed to be able to declare the
-- following generic packages. They are repeated in GNATCOLL.SQL for ease
-- of use.
type Table_Names is record
Name : Cst_String_Access;
Instance : Cst_String_Access;
Instance_Index : Integer := -1;
-- The name of the instance is either Instance (if not null), or
-- computed from the index (see Numbered_Tables above) if not -1, or the
-- name of the table
end record;
No_Names : constant Table_Names := (null, null, -1);
-- Describes a table (by its name), and the name of its instance. This is
-- used to find all tables involved in a query, for the auto-completion. We
-- do not store instances of SQL_Table'Class directly, since that would
-- involve several things:
-- - extra Initialize/Adjust/Finalize calls
-- - Named_Field_Internal would need to embed a pointer to a table, as
-- opposed to just its names, and therefore must be a controlled type.
-- This makes the automatic package more complex, and makes the field
-- type controlled, which is also a lot more costly.
-- The contents of this type is the same as the discriminants for SQL_Table
-- and SQL_Field (but unfortunately cannot be used directly as the
-- discriminant).
function Instance_Name (Names : Table_Names) return String;
-- Return the name of the instance for that table.
function Hash (Self : Table_Names) return Ada.Containers.Hash_Type;
package Table_Sets is new Ada.Containers.Indefinite_Hashed_Sets
(Table_Names, Hash, "=", "=");
type SQL_Table_Or_List is abstract tagged private;
-- Either a single table or a group of tables
procedure Append_Tables
(Self : SQL_Table_Or_List; To : in out Table_Sets.Set) is null;
-- Append all the tables referenced in Self to To
function To_String
(Self : SQL_Table_Or_List; Format : Formatter'Class)
return String is abstract;
-- Convert the table to a string
type SQL_Single_Table (Instance : GNATCOLL.SQL_Impl.Cst_String_Access;
Instance_Index : Integer)
is abstract new SQL_Table_Or_List with private;
-- Any type of table, or result of join between several tables. Such a
-- table can have fields
-------------------------------------
-- General declarations for fields --
-------------------------------------
type SQL_Assignment is private;
type SQL_Field_Or_List is abstract tagged null record;
-- Either a single field or a list of fields
function To_String
(Self : SQL_Field_Or_List;
Format : Formatter'Class;
Long : Boolean := True) return String
is abstract;
-- Convert the field to a string. If Long is true, a fully qualified
-- name is used (table.name), otherwise just the field name is used
type SQL_Field_List is new SQL_Field_Or_List with private;
Empty_Field_List : constant SQL_Field_List;
-- A list of fields, as used in a SELECT query ("field1, field2");
function Is_Empty (List : SQL_Field_List) return Boolean;
overriding function To_String
(Self : SQL_Field_List;
Format : Formatter'Class;
Long : Boolean := True) return String;
-- See inherited doc
type SQL_Field (Table : Cst_String_Access;
Instance : Cst_String_Access;
Name : Cst_String_Access;
Instance_Index : Integer)
is abstract new SQL_Field_Or_List with null record;
-- A field that comes directly from the database. It can be within a
-- specific table instance, but we still need to know the name of the table
-- itself for the autocompletion.
-- (Table,Instance) might be null if the field is a constant.
-- The discriminants are used to get the name of the table when displaying
-- the field, while permitting static constructs like:
-- Ta_Names : constant Cst_String_Access := ...;
-- type T_Names (Instance : Cst_String_Access)
-- is new SQL_Table (Ta_Names, Instance, -1)
-- with record
-- Id : SQL_Field_Integer (Ta_Names, Instance, -1);
-- end record;
-- so that one can define multiple representations of the Names table, as
-- in:
-- T1 : T_Names (null); -- Default, name will be "names"
-- T2 : T_Names (Ta_Names2); -- An alias
-- In both cases, the fields T1.Id and T2.Id automatically know how to
-- display themselves as "names.id" and "names2.id". This does not
-- require memory allocation and is thus more efficient.
overriding function To_String
(Self : SQL_Field;
Format : Formatter'Class;
Long : Boolean := True) return String;
-- See inherited doc
procedure Append_Tables (Self : SQL_Field; To : in out Table_Sets.Set);
-- Append the table(s) referenced by Self to To.
-- This is used for auto-completion later on
procedure Append_If_Not_Aggregate
(Self : SQL_Field;
To : in out SQL_Field_List'Class;
Is_Aggregate : in out Boolean);
-- Append all fields referenced by Self if Self is not the result of an
-- aggregate function. This is used for autocompletion of "group by".
-- Is_Aggregate is set to True if Self is an aggregate, untouched otherwise
procedure Append (List : in out SQL_Field_List; Field : SQL_Field'Class);
function "&" (Left, Right : SQL_Field'Class) return SQL_Field_List;
function "&" (Left, Right : SQL_Field_List) return SQL_Field_List;
function "&"
(Left : SQL_Field_List; Right : SQL_Field'Class) return SQL_Field_List;
function "&"
(Left : SQL_Field'Class; Right : SQL_Field_List) return SQL_Field_List;
-- Create lists of fields
function "+" (Left : SQL_Field'Class) return SQL_Field_List;
-- Create a list with a single field
package Field_List is new Ada.Containers.Indefinite_Vectors
(Natural, SQL_Field'Class);
function First (List : SQL_Field_List) return Field_List.Cursor;
-- Return the first field contained in the list
--------------------
-- Field pointers --
--------------------
-- A smart pointer that frees memory whenever the field is no longer needed
type SQL_Field_Pointer is private;
No_Field_Pointer : constant SQL_Field_Pointer;
-- A smart pointer
function "+" (Field : SQL_Field'Class) return SQL_Field_Pointer;
-- Create a new pointer. Memory will be deallocated automatically
procedure Append
(List : in out SQL_Field_List'Class; Field : SQL_Field_Pointer);
-- Append a new field to the list
function To_String
(Self : SQL_Field_Pointer;
Format : Formatter'Class;
Long : Boolean) return String;
procedure Append_Tables
(Self : SQL_Field_Pointer; To : in out Table_Sets.Set);
procedure Append_If_Not_Aggregate
(Self : SQL_Field_Pointer;
To : in out SQL_Field_List'Class;
Is_Aggregate : in out Boolean);
-- See doc for SQL_Field
----------------
-- Field data --
----------------
-- There are two kinds of fields: one is simple fields coming straight from
-- the database ("table.field"), the other are fields computed through this
-- API ("field1 || field2", Expression ("field"), "field as name"). The
-- latter need to allocate memory to store their contents, and are stored
-- in a refcounted type internally, so that we can properly manage memory.
type SQL_Field_Internal is abstract tagged null record;
-- Data that can be stored in a field
procedure Free (Self : in out SQL_Field_Internal) is null;
procedure Free_Dispatch (Self : in out SQL_Field_Internal'Class);
function To_String
(Self : SQL_Field_Internal;
Format : Formatter'Class;
Long : Boolean) return String is abstract;
procedure Append_Tables
(Self : SQL_Field_Internal; To : in out Table_Sets.Set) is null;
procedure Append_If_Not_Aggregate
(Self : access SQL_Field_Internal; -- for dispatching
To : in out SQL_Field_List'Class;
Is_Aggregate : in out Boolean) is null;
-- The three subprograms are equivalent to the ones for SQL_Field. When a
-- field contains some data, it will simply delegate the calls to the above
-- subprograms.
-- Self_Field is added to the list. Self_Field.Get must be equal to Self
package Field_Pointers is new Shared_Pointers
(SQL_Field_Internal'Class, Free_Dispatch);
subtype SQL_Field_Internal_Access is Field_Pointers.Element_Access;
generic
type Base_Field is abstract new SQL_Field with private;
package Data_Fields is
type Field is new Base_Field with record
Data : Field_Pointers.Ref;
end record;
overriding function To_String
(Self : Field;
Format : Formatter'Class;
Long : Boolean := True) return String;
overriding procedure Append_Tables
(Self : Field; To : in out Table_Sets.Set);
overriding procedure Append_If_Not_Aggregate
(Self : Field;
To : in out SQL_Field_List'Class;
Is_Aggregate : in out Boolean);
end Data_Fields;
-- Mixin inheritand for a field, to add specific user data to them. This
-- user data is refcounted. Field just acts as a proxy for Data, and
-- delegates all its operations to Data.
----------------------------------------
-- General declarations for criterias --
----------------------------------------
type SQL_Criteria is private;
No_Criteria : constant SQL_Criteria;
function To_String
(Self : SQL_Criteria;
Format : Formatter'Class;
Long : Boolean := True) return String;
procedure Append_Tables (Self : SQL_Criteria; To : in out Table_Sets.Set);
procedure Append_If_Not_Aggregate
(Self : SQL_Criteria;
To : in out SQL_Field_List'Class;
Is_Aggregate : in out Boolean);
-- The usual semantics for these subprograms (see SQL_Field)
type SQL_Criteria_Data is abstract tagged null record;
-- The data contained in a criteria. You can create new versions of it if
-- you need to create new types of criterias
procedure Free (Self : in out SQL_Criteria_Data) is null;
procedure Free_Dispatch (Self : in out SQL_Criteria_Data'Class);
function To_String
(Self : SQL_Criteria_Data;
Format : Formatter'Class;
Long : Boolean := True) return String
is abstract;
procedure Append_Tables
(Self : SQL_Criteria_Data; To : in out Table_Sets.Set) is null;
procedure Append_If_Not_Aggregate
(Self : SQL_Criteria_Data;
To : in out SQL_Field_List'Class;
Is_Aggregate : in out Boolean) is null;
-- See description of these subprograms for a SQL_Criteria
procedure Set_Data
(Self : in out SQL_Criteria; Data : SQL_Criteria_Data'Class);
package SQL_Criteria_Pointers
is new Shared_Pointers (SQL_Criteria_Data'Class, Free_Dispatch);
subtype SQL_Criteria_Data_Access is
SQL_Criteria_Pointers.Element_Access;
function Get_Data (Self : SQL_Criteria) return SQL_Criteria_Data_Access;
-- Set the data associated with Self.
-- This is only needed when you implement your own kinds of criteria, not
-- when writing SQL queries.
function Compare
(Left, Right : SQL_Field'Class;
Op : Cst_String_Access;
Suffix : Cst_String_Access := null)
return SQL_Criteria;
-- Used to write comparison operations. This is a low-level implementation,
-- which should only be used when writing your own criterias, not when
-- writing queries.
-- The operation is written as
-- Left Op Right Suffix
function Compare1
(Field : SQL_Field'Class;
Op : Cst_String_Access;
Suffix : Cst_String_Access := null)
return SQL_Criteria;
-- Apply a function to a field, as in:
-- Op Field Suffix (Op or Suffix can contain parenthesis)
------------------------------------------
-- General declarations for assignments --
------------------------------------------
No_Assignment : constant SQL_Assignment;
function "&" (Left, Right : SQL_Assignment) return SQL_Assignment;
-- Concat two assignments
procedure Append_Tables (Self : SQL_Assignment; To : in out Table_Sets.Set);
function To_String
(Self : SQL_Assignment;
Format : Formatter'Class;
With_Field : Boolean) return String;
-- The usual semantics for these subprograms (see fields)
procedure To_List (Self : SQL_Assignment; List : out SQL_Field_List);
-- Return the list of values in Self as a list of fields. This is used for
-- statements likes "INSERT INTO ... SELECT list"
procedure Get_Fields (Self : SQL_Assignment; List : out SQL_Field_List);
-- Return the list of fields impacted by the assignments
function Create (F1, F2 : SQL_Field'Class) return SQL_Assignment;
-- A generic way to create assignments
--------------
-- Generics --
--------------
-- The following package can be used to create your own field types, based
-- on specific Ada types. It creates various subprograms for ease of use
-- when writing queries, as well as subprograms to more easily bind SQL
-- functions manipulating this type.
generic
type Ada_Type (<>) is private;
with function To_SQL
(Format : Formatter'Class;
Value : Ada_Type;
Quote : Boolean) return String;
-- Converts Ada_Type to a value suitable to pass to SQL. This should
-- protect special characters if need be and if Quote is True.
-- This function can also be used to add constraints on the types
-- supported by these fields.
-- You can often rely on Ada's builtin checks (for instance an integer
-- field that accepts values from 1 to 10 would be instantiated with an
-- Ada type
-- type My_Type is new Integer range 1 .. 10;
-- and that would work. However, this isn't always doable. For instance,
-- to represent a string field with a _maximum_ length of 10, we cannot
-- instantiate it with String (1 .. 10), since that would only allow
-- strings of _exactly_ 10 character. In such a case, we should
-- implement Check_Value to ensure the max length of the string.
-- This procedure should raise Constraint_Error in case of error.
type Param_Type is new SQL_Parameter_Type with private;
-- Internal type to use for the parameter
package Field_Types is
type Field is new SQL_Field with null record;
function From_Table
(Self : Field;
Table : SQL_Single_Table'Class) return Field'Class;
-- Returns field applied to the table, as in Table.Field.
-- In general, this is not needed, except when Table is the result of a
-- call to Rename on a table generated by a call to Left_Join for
-- instance. In such a case, the list of valid fields for Table is not
-- known, and we do not have primitive operations to access those, so
-- this function makes them accessible. However, there is currently no
-- check that Field is indeed valid for Table.
Null_Field : constant Field;
function Expression (Value : Ada_Type) return Field'Class;
-- Create a constant field
function From_String (SQL : String) return Field'Class;
-- Similar to the above, but the parameter is assumed to be proper SQL
-- already (so for instance no quoting or special-character quoting
-- would occur for strings). This function just indicates to GNATCOLL
-- how the string should be interpreted
function Param (Index : Positive) return Field'Class;
-- Return a special string that will be inserted in the query, and
-- can be substituted with an actual value when the query is executed.
-- This is used to parameterize queries. In particular, this allows you
-- to prepare a general form of the query, as in:
-- SELECT * FROM table WHERE table.field1 = ?1
-- and execute this several times, substituting a different value
-- every time.
-- This is more efficient in general (since the statement is prepared
-- only once, although the preparation cannot take advantage of special
-- knowledge related to the value), and safer (no need to worry about
-- specially quoting the actual value, which GNATCOLL would do for you
-- but potentially there might still be issues).
-- The exact string inserted depends on the DBMS.
function "&"
(Field : SQL_Field'Class; Value : Ada_Type) return SQL_Field_List;
function "&"
(Value : Ada_Type; Field : SQL_Field'Class) return SQL_Field_List;
function "&"
(List : SQL_Field_List; Value : Ada_Type) return SQL_Field_List;
function "&"
(Value : Ada_Type; List : SQL_Field_List) return SQL_Field_List;
-- Create lists of fields
function "=" (Left : Field; Right : Field'Class) return SQL_Criteria;
function "/=" (Left : Field; Right : Field'Class) return SQL_Criteria;
function "<" (Left : Field; Right : Field'Class) return SQL_Criteria;
function "<=" (Left : Field; Right : Field'Class) return SQL_Criteria;
function ">" (Left : Field; Right : Field'Class) return SQL_Criteria;
function ">=" (Left : Field; Right : Field'Class) return SQL_Criteria;
function "=" (Left : Field; Right : Ada_Type) return SQL_Criteria;
function "/=" (Left : Field; Right : Ada_Type) return SQL_Criteria;
function "<" (Left : Field; Right : Ada_Type) return SQL_Criteria;
function "<=" (Left : Field; Right : Ada_Type) return SQL_Criteria;
function ">" (Left : Field; Right : Ada_Type) return SQL_Criteria;
function ">=" (Left : Field; Right : Ada_Type) return SQL_Criteria;
pragma Inline ("=", "/=", "<", ">", "<=", ">=");
-- Compare fields and values
function Greater_Than
(Left : SQL_Field'Class; Right : Field) return SQL_Criteria;
function Greater_Or_Equal
(Left : SQL_Field'Class; Right : Field) return SQL_Criteria;
function Equal
(Left : SQL_Field'Class; Right : Field) return SQL_Criteria;
function Less_Than
(Left : SQL_Field'Class; Right : Field) return SQL_Criteria;
function Less_Or_Equal
(Left : SQL_Field'Class; Right : Field) return SQL_Criteria;
function Greater_Than
(Left : SQL_Field'Class; Right : Ada_Type) return SQL_Criteria;
function Greater_Or_Equal
(Left : SQL_Field'Class; Right : Ada_Type) return SQL_Criteria;
function Equal
(Left : SQL_Field'Class; Right : Ada_Type) return SQL_Criteria;
function Less_Than
(Left : SQL_Field'Class; Right : Ada_Type) return SQL_Criteria;
function Less_Or_Equal
(Left : SQL_Field'Class; Right : Ada_Type) return SQL_Criteria;
pragma Inline
(Greater_Than, Greater_Or_Equal, Equal, Less_Than, Less_Or_Equal);
-- Same as "<", "<=", ">", ">=" and "=", but these can be used with the
-- result of aggregate fields for instance. In general, you should not
-- use these to work around typing issues (for instance comparing a text
-- field with 1234)
function "=" (Self : Field; Value : Ada_Type) return SQL_Assignment;
function "=" (Self : Field; To : Field'Class) return SQL_Assignment;
-- Set Field to the value of To
-- Assign a new value to the value
generic
Name : String;
function Operator (Field1, Field2 : SQL_Field'Class) return Field'Class;
-- An operator between two fields, that return a field of the new type
generic
Name : String;
Prefix : String := "";
Suffix : String := "";
function String_Operator
(Self : SQL_Field'Class; Operand : String) return Field'Class;
generic
type Scalar is (<>);
Name : String;
Prefix : String := "";
Suffix : String := "";
function Scalar_Operator
(Self : SQL_Field'Class; Operand : Scalar) return Field'Class;
-- An operator between a field and a constant value, as in
-- field + interval '2 days'
-- where Name is "+"
-- Prefix is "interval '"
-- Suffix is " days'"
generic
Name : String;
function SQL_Function return Field'Class;
-- A no-parameter sql function, as in "CURRENT_TIMESTAMP"
generic
type Argument_Type is abstract new SQL_Field with private;
Name : String;
Suffix : String := ")";
function Apply_Function (Self : Argument_Type'Class) return Field'Class;
-- Applying a function to a field, as in "LOWER (field)", where
-- Name is "LOWER ("
-- Suffix is ")"
function Cast_Implicit (Self : SQL_Field'Class) return Field'Class;
-- Convert any field type to this package provided implicitly
generic
type Argument1_Type is abstract new SQL_Field with private;
type Argument2_Type is abstract new SQL_Field with private;
Name : String;
Suffix : String := ")";
function Apply_Function2
(Arg1 : Argument1_Type'Class;
Arg2 : Argument2_Type'Class)
return Field'Class;
-- Applying a function to two fields, and return another field
function Nullif (Left, Right : SQL_Field'Class) return Field'Class;
-- SQL NULLIF function
private
Null_Field : constant Field :=
(Table => null,
Instance => null,
Instance_Index => -1,
Name => Null_String'Access);
end Field_Types;
private
type SQL_Field_List is new SQL_Field_Or_List with record
List : Field_List.Vector;
end record;
type SQL_Table_Or_List is abstract tagged null record;
type SQL_Single_Table (Instance : Cst_String_Access;
Instance_Index : Integer)
is abstract new SQL_Table_Or_List with null record;
-- instance name, might be null when this is the same name as the table.
-- This isn't used for lists, but is used for all other types of tables
-- (simple, left join, subqueries) so is put here for better sharing.
---------------
-- Criterias --
---------------
type SQL_Criteria is record
Criteria : SQL_Criteria_Pointers.Ref;
end record;
-- SQL_Criteria must not be tagged, otherwise we have subprograms that are
-- primitive for two types. This would also be impossible for users to
-- declare a variable of type SQL_Criteria.
No_Criteria : constant SQL_Criteria :=
(Criteria => SQL_Criteria_Pointers.Null_Ref);
--------------------
-- Field pointers --
--------------------
package SQL_Field_Pointers is new Shared_Pointers (SQL_Field'Class);
type SQL_Field_Pointer is new SQL_Field_Pointers.Ref with null record;
No_Field_Pointer : constant SQL_Field_Pointer :=
(SQL_Field_Pointers.Null_Ref with null record);
-----------------
-- Assignments --
-----------------
type Assignment_Item is record
Field : SQL_Field_Pointer;
-- The modified field
To_Field : SQL_Field_Pointer;
-- Its new value (No_Field_Pointer sets to NULL)
end record;
package Assignment_Lists is new Ada.Containers.Vectors
(Natural, Assignment_Item);
type SQL_Assignment is record
List : Assignment_Lists.Vector;
end record;
No_Assignment : constant SQL_Assignment :=
(List => Assignment_Lists.Empty_Vector);
Empty_Field_List : constant SQL_Field_List :=
(SQL_Field_Or_List with List => Field_List.Empty_Vector);
end GNATCOLL.SQL_Impl;
|