All global functions
void set_debug_callback( function(mixed...:void) <b>to</b> )
The debug callback will be called with one or more arguments that describe what the luke database abstraction system is currently doing.

Luke.db.DBObj get_any_obj( int <b>id</b> )
Returns the object representing the database object 'id', if any

array connect( )
Connect to all database servers that are currently up. This is a requirement for writing in the database, but not for reading.

Returns an array with one ({ object server, int uid, string server_name }) entry for each server.

array(Luke.db.User) users( )

array(Luke.db.Group) groups( )

array(Luke.db.Favourite) favourites( )

array(Luke.db.Artists) artists( )

array(Luke.db.Collection) collections( )

array(Luke.db.Multimedia) multimedias( )

array(Luke.db.Folder) folders( )

array(Luke.db.Style) styles( )

array(Luke.db.Song) songs( )
These functions return an array with all the objects of the specified type.

The functions are optimized to do multiple paralllel requests if possible (when threads are available), and they are always optimized to only do one request to each database server.

array(Luke.db.DBObj)|Luke.db.DBObj find( string <b>type</b>, string <b>glob_pattern</b>, int|void all )
Find the first, or if 'all' is specified, all objects of the specified type matching the supplied glob pattern.
Pike v0.7 release 60 running Hilfe v2.0 (Incremental Pike Frontend)
> Luke.db.find( "artist", "*Sister*", 1 );
Result: ({ /* 2 elements */
            Artist(62548 /*Pointer Sisters, The*/),
            Artist(10728 /*Sisters of Mercy*/)
        })
> Luke.db.find( "artist", "*Sister*", 0 );
Result: Artist(62548 /*Pointer Sisters, The*/)

int recursively_find( Luke.db.DBObj <b>hay</b>, Luke.db.DBObj <b>needle</b> )
Return true if needle is or is a child of hay.

void enqueue_async( int <b>id</b> )
Fetch id at some time in the future.

void watch_new( function <b>callback</b>, string|void type_to_watch> )
Call the specified callback function when a new database object of the type type_to_watch, or if no type is specified, any type, is created.

The basic database object class
All database object inherit this class, which defines some functions and variables that are therefore available in all database objects.

class DBObj
{
  int play( int|function score, object playd_server, int relative_points );
  mixed user_data( string name );
  mixed set_user_data( string name, mixed to );
  object my_server();
  void add_aquire_callback( function when_fetched, void|mixed extra_arg );
  void add_modify_callback( function cb );
  int modify( mapping changes );
  void save(); /*Not tested/

  int id;
  string name;
  string description;

  string type;
  string server;
  string icon, large_icon;
  int invisible;

  Luke.db.User owner;
  Luke.db.Group group;

  int ctime, mtime;
  int mode;

  array(Luke.db.MultiMedia multimedior; /*(internal joke.. )*/
}
There is also a rather special rule: Prefixing 'recursively_' before any function or variable name will return an array of the given index in this object, and all the children of this object.

So:

> object artist = Luke.db.artists()[125];
Result: Artist(14634 /*Blümchen*/)
> artist->children();   
Result: ({ /* 3 elements */
            Collection(61349 /*Blandat*/),
            Collection(62371 /*Jasmin*/),
            Collection(62502 /*Verliebt*/)
        })
> artist->recursively_name;
Result: ({ /* 34 elements */
            "Blümchen",
            "Blandat",
            "Bicycle Race",
            "Boomerang",
            "Herz an Herz",
            "Kleiner Satellit",
            "Jasmin",
            "Ich bin wieder hier",
            "Automatisch",
            "Blaue augen",
            "Immer noch verliebt",
            "Denk noch mal drüber nach",
            "Willkommen in meinem garten",
            "Hand in hand (gewalt ist doof!)",
            "Ganz bald",
            "Der beste von allen",
            "U-bahn",
            "So wie ein wunder",
            "Nur für euch",
            "Es ist vorbei",
            "Nur geträumt",
            "Verliebt",
            "Nur Getraumt",
            "Schmetterlinge 1998",
            "Du Bist Die Insel",
            "Er Liebt Mich",
            "Ubermorgenland",
            "Gib Mir Noch Zeit",
            "Eisblumen",
            "Reise Durch Die Zeit",
            "Achterbahn",
            "Engel Der Nacht",
            "S.O.S Herz In Not",
            "Verrückte Jungs"
        })
The different object classes
class Folder /* Container with coordinates for the children */
{
  array children_map( ) /* ({ ([ "x":xpos, "y":ypos, "obj":dbobj ]), ... }) */
  array children();

  void multiple_add();
  void add( Luke.db.DBObj what, int x, int y );
  void remove( Luke.db.DBObj what );
  void commit();
}



class Favourites
{
  Luke.db.User judge;
  array list;
  array nolist;

 /*
    The actual favourite list is
    flatten(list->recursively_children()) - 
    flatten(nolist->recursively_children())
 */

  array children();
  void add( Luke.db.DBObj what );
  void remove( Luke.db.DBObj what );
}

class Group
{
  array(Luke.db.User) members;
  array children();
}

class User
{
   string last_seen_on;
   int last_login;
   array(Luke.db.Group) groups;
   array(Luke.db.Favourite) playlists;
   Luke.db.Favourite favourites;
   Luke.db.Folder root_folder;
}

class MpegStream
{
   int available;
   int bitrate;
   int channels;
   int copyright;
   int layer;
   int orig;
   int rate;
   int header;

   float len;
   float set_len;
  
   int min;
   float sec;
}

class Song
{
  int track_no;
  int volume;

  array(Luke.db.Collection) collections;
  array(Luke.db.Artist) artists;
  array(Luke.db.Artist) composers;
  Luke.db.Lyrics lyrics;
  array(Luke.db.Style) style;     /* Use list_style instead. */

  Luke.db.Artist artist;          /* these are not all that accurate */
  Luke.db.Collection collection;  /* when there is more than one artist */
                                  /* or collection this song belongs to */
  
  Luke.db.DBObj music_data;

  string long();
  string describe( int short_mode );
  
  string get_style();
  array(Luke.db.Style) list_style();
}

class Lyrics
{
  Luke.db.Song song;
  array(mapping) persons;
  array(mapping) types;
  array(mapping) events; 
/* ({ ([ "type":int, "person":int, "text":string, "tyme":float ]) }) */
}

class Artist
{
  array performs_on;
  array composed_on;
  array style = ({});

  int num_songs;
 
  array children();   /* return all visible collections */
  array collections(); /* also returns invisible collections */

  array list_style();
}

class MultiMedia
{
  string mm_type;
  string mm_subtype;
  string mm_data;
  mapping pointers = ([]);

  MultiMedia fullsize();
  mapping image_objects(int|void pike_image_object); 
  /* by default GDK.Pixmap/Bitmap */
}

class Collection
{
  array artists;
  object artist; /* first of the above */
  string media_type;
  array style = ({});
  int prod_year;
  
  int num_songs;

  array children();    /* return all visible songs */
  array songs();      /* also returns invisible songs */

  array list_style();
}


class Style
{
  array(object) children();
}
Some small examples
All artist names:
 Luke.db.artists()->name;
The name of all artists, collections and songs in the database (SLOW!)
 Luke.db.artists()->recursively_name;