Index: trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- trunk/FACT++/src/InterpreterV8.cc	(revision 14579)
+++ trunk/FACT++/src/InterpreterV8.cc	(revision 14591)
@@ -397,9 +397,6 @@
 Handle<Value> InterpreterV8::FuncDbQuery(const Arguments &args)
 {
-    if (args.Length()!=1)
-        return ThrowException(String::New("Number of arguments must be exactly 1."));
-
-    if (!args[0]->IsString())
-        return ThrowException(String::New("Both arguments must be a string."));
+    if (args.Length()==0)
+        return ThrowException(String::New("Arguments expected."));
 
     HandleScope handle_scope;
@@ -409,5 +406,8 @@
         return Undefined();
 
-    const String::Utf8Value query(args[0]);
+    string query;
+    for (int i=0; i<args.Length(); i++)
+        query += string(" ") + *String::Utf8Value(args[i]);
+    query.erase(0, 1);
 
 #ifdef HAVE_SQL
@@ -416,8 +416,9 @@
         Database *db = reinterpret_cast<Database*>(ptr);
 
-        const mysqlpp::StoreQueryResult res = db->query(*query).store();
+        const mysqlpp::StoreQueryResult res = db->query(query).store();
 
         Handle<Array> ret = Array::New();
-        ret->Set(String::New("table"), String::New(res.table()), ReadOnly);
+        ret->Set(String::New("table"), String::New(res.table()),   ReadOnly);
+        ret->Set(String::New("query"), String::New(query.c_str()), ReadOnly);
 
         Handle<Array> cols = Array::New();
@@ -434,5 +435,5 @@
                 const Handle<Value> name = String::New((*list)[i].c_str());
                 if (irow==0)
-                    cols->Set(Integer::NewFromUnsigned(i), name, ReadOnly);
+                    cols->Set(i, name);
 
                 if ((*it)[i].is_null())
@@ -528,5 +529,5 @@
             }
 
-            ret->Set(Integer::NewFromUnsigned(irow++), row, ReadOnly);
+            ret->Set(irow++, row);
         }
 
@@ -546,18 +547,15 @@
 {
     if (args.Length()!=1)
-        return ThrowException(String::New("Number of arguments must be exactly 1."));
+        return ThrowException(String::New("Number of arguments must be 1."));
 
     if (!args[0]->IsString())
-        return ThrowException(String::New("Argument 1 must be a string."));
-
-    HandleScope handle_scope;
-
-    const String::Utf8Value database(args[0]);
-    const String::Utf8Value query   (args[1]);
+        return ThrowException(String::New("Argument 1 not a string."));
+
+    HandleScope handle_scope;
 
 #ifdef HAVE_SQL
     try
     {
-        Database *db = new Database(*database);
+        Database *db = new Database(*String::Utf8Value(args[0]));
         fDatabases.push_back(db);
 
@@ -1084,4 +1082,53 @@
 }
 
+Handle<Value> InterpreterV8::LocalDist(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()!=2)
+        return ThrowException(String::New("dist must not be called with two arguments."));
+
+    if (!args[0]->IsObject() || !args[1]->IsObject())
+        return ThrowException(String::New("at least one argument not an object."));
+
+    Handle<Object> obj[2] =
+    {
+        Handle<Object>::Cast(args[0]),
+        Handle<Object>::Cast(args[1])
+    };
+
+    const Handle<String> s_zd = String::New("zd");
+    const Handle<String> s_az = String::New("az");
+
+    const double zd0 = obj[0]->Get(s_zd)->NumberValue() * M_PI/180;
+    const double az0 = obj[0]->Get(s_az)->NumberValue() * M_PI/180;
+    const double zd1 = obj[1]->Get(s_zd)->NumberValue() * M_PI/180;
+    const double az1 = obj[1]->Get(s_az)->NumberValue() * M_PI/180;
+
+    if (!finite(zd0) || !finite(zd1) || !finite(az0) || !finite(az1))
+        return ThrowException(String::New("some values not valid or not finite."));
+
+    /*
+    const double x0 = sin(zd0) * cos(az0);   // az0 -= az0
+    const double y0 = sin(zd0) * sin(az0);   // az0 -= az0
+    const double z0 = cos(zd0);
+
+    const double x1 = sin(zd1) * cos(az1);   // az1 -= az0
+    const double y1 = sin(zd1) * sin(az1);   // az1 -= az0
+    const double z1 = cos(zd1);
+
+    const double res = acos(x0*x1 + y0*y1 + z0*z1) * 180/M_PI;
+    */
+
+    // cos(az1-az0) = cos(az1)*cos(az0) + sin(az1)*sin(az0)
+
+    const double x = sin(zd0) * sin(zd1) * cos(az1-az0);
+    const double y = cos(zd0) * cos(zd1);
+
+    const double res = acos(x + y) * 180/M_PI;
+
+    return handle_scope.Close(Number::New(res));
+}
+
 Handle<Value> InterpreterV8::MoonDisk(const Arguments &args)
 {
@@ -1094,5 +1141,5 @@
     const Time utc = args.Length()==0 ? Time() : Time(v/1000, v%1000);
 
-    handle_scope.Close(Number::New(ln_get_lunar_disk(utc.JD())));
+    return handle_scope.Close(Number::New(ln_get_lunar_disk(utc.JD())));
 }
 
@@ -1438,4 +1485,5 @@
 
     Handle<FunctionTemplate> loc = FunctionTemplate::New(ConstructorLocal);
+    loc->Set(String::New("dist"), FunctionTemplate::New(LocalDist), ReadOnly);
     global->Set(String::New("Local"), loc, ReadOnly);
 
Index: trunk/FACT++/src/InterpreterV8.h
===================================================================
--- trunk/FACT++/src/InterpreterV8.h	(revision 14579)
+++ trunk/FACT++/src/InterpreterV8.h	(revision 14591)
@@ -72,4 +72,5 @@
     static v8::Handle<v8::Value> ConstructLocal(double zd, double az, v8::Handle<v8::Value> time=v8::Handle<v8::Value>());
     static v8::Handle<v8::Value> ConstructSky(double ra, double dec, v8::Handle<v8::Value> time=v8::Handle<v8::Value>(), bool ismoon=false);
+    static v8::Handle<v8::Value> LocalDist(const v8::Arguments &args);
     static v8::Handle<v8::Value> MoonDisk(const v8::Arguments &args);
     static v8::Handle<v8::Value> LocalToSky(const v8::Arguments &args);
