diff --git a/api/0.2.2/DB.html b/api/0.2.2/DB.html new file mode 100644 index 0000000..0563c60 --- /dev/null +++ b/api/0.2.2/DB.html @@ -0,0 +1,532 @@ + + + + + + + + DB - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + module DB + +

+ + + + + +

Overview

+ +

The DB module is a unified interface to database access. +Database dialects is supported by custom database driver shards. +Check manastech/crystal-sqlite3 for example.

+ +

Drivers implementors check Driver class.

+ +

DB manage a connection pool. The connection pool can be configured by URI query. See Database.

+ +

Usage

+ +

Assuming crystal-sqlite3 is included a sqlite3 database can be opened with #open.

+ +
db = DB.open "sqlite3:./path/to/db/file.db"
+db.close
+ +

If a block is given to #open the database is closed automatically

+ +
DB.open "sqlite3:./file.db" do |db|
+  # work with db
+end # db is closed
+ +

In the code above db is a Database. Methods available for querying it are described in QueryMethods.

+ +

Three kind of statements can be performed:

+ +
  1. Database#exec waits no response from the database.
  2. Database#scalar reads a single value of the response.
  3. Database#query returns a ResultSet that allows iteration over the rows in the response and column information.
+ +

All of the above methods allows parametrised query. Either positional or named arguments.

+ +

Check a full working version:

+ +
require "db"
+require "sqlite3"
+
+DB.open "sqlite3:./file.db" do |db|
+  db.exec "create table contacts (name string, age integer)"
+  db.exec "insert into contacts values (?, ?)", "John Doe", 30
+
+  args = [] of DB::Any
+  args << "Sarah"
+  args << 33
+  db.exec "insert into contacts values (?, ?)", args
+
+  puts "max age:"
+  puts db.scalar "select max(age) from contacts" # => 33
+
+  puts "contacts:"
+  db.query "select name, age from contacts order by age desc" do |rs|
+    puts "#{rs.column_name(0)} (#{rs.column_name(1)})"
+    # => name (age)
+    rs.each do
+      puts "#{rs.read(String)} (#{rs.read(Int32)})"
+      # => Sarah (33)
+      # => John Doe (30)
+    end
+  end
+end
+ + + + + + + + + + + + + + +

Defined in:

+ + + db.cr + +
+ + + db/pool.cr + +
+ + + db/string_key_cache.cr + +
+ + + db/query_methods.cr + +
+ + + db/disposable.cr + +
+ + + db/database.cr + +
+ + + db/driver.cr + +
+ + + db/connection.cr + +
+ + + db/statement.cr + +
+ + + db/pool_statement.cr + +
+ + + db/result_set.cr + +
+ + + db/error.cr + +
+ + + db/mapping.cr + +
+ + + db/version.cr + +
+ + + + + +

Constant Summary

+ +
+ +
+ TYPES = [Nil, String, Int32, Int64, Float32, Float64, Bytes] +
+ +
+

Types supported to interface with database driver. +These can be used in any ResultSet#read or any Database#query related +method to be used as query parameters

+
+ + +
+ VERSION = "0.2.2" +
+ + +
+ + + +

Class Method Summary

+ + + + + + +

Macro Summary

+ + + + +
+ +
+ + +

Class Method Detail

+ +
+
+ + def self.open(uri : URI | String) + + # +
+ +

Opens a database using the specified uri. +The scheme of the uri determines the driver to use. +Returned database must be closed by Database#close. +If a block is used the database is yielded and closed automatically.

+ +
+
+ + [View source] + +
+
+ +
+
+ + def self.open(uri : URI | String, &block) + + # +
+ +

Same as #open but the database is yielded and closed automatically.

+ +
+
+ + [View source] + +
+
+ +
+
+ + def self.register_driver(driver_name, driver_class : Driver.class) + + # +
+ +

Registers a driver class for a given driver_name. +Should be called by drivers implementors only.

+ +
+
+ + [View source] + +
+
+ + + + + + +

Macro Detail

+ +
+
+ + macro mapping(properties, strict = true) + + # +
+ +

The DB.mapping macro defines how an object is built from a DB::ResultSet.

+ +

It takes hash literal as argument, in which attributes and types are defined. +Once defined, DB::ResultSet#read(t) populates properties of the class from the +result set.

+ +
require "db"
+
+class Employee
+  DB.mapping({
+    title: String,
+    name:  String,
+  })
+end
+
+employees = Employee.from_rs(db.query("SELECT title, name FROM employees"))
+employees[0].title # => "Manager"
+employees[0].name  # => "John"
+ +

Attributes not mapped with DB.mapping are not defined as properties. +Also, missing attributes raise a DB::Exception.

+ +

You can also define attributes for each property.

+ +
class Employee
+  DB.mapping({
+    title: String,
+    name:  {
+      type:    String,
+      nilable: true,
+      key:     "firstname",
+    },
+  })
+end
+ +

Available attributes:

+ +
  • type (required) defines its type. In the example above, title: String is a shortcut to title: {type: String}.
  • nilable defines if a property can be a Nil.
  • default: value to use if the property is missing in the result set, or if it's null and nilable was not set to true. If the default value creates a new instance of an object (for example [1, 2, 3] or SomeObject.new), a different instance will be used each time a row is parsed.
  • key defines which column to read from a reusltset. It defaults to the name of the property.
  • converter takes an alternate type for parsing. It requires a #from_rs method in that class, and returns an instance of the given type.
+ +

The mapping also automatically defines Crystal properties (getters and setters) for each +of the keys. It doesn't define a constructor accepting those arguments, but you can provide +an overload.

+ +

The macro basically defines a constructor accepting a DB::ResultSet that reads from +it and initializes this type's instance variables.

+ +

This macro also declares instance variables of the types given in the mapping.

+ +
+
+ + [View source] + +
+
+ +
+
+ + macro mapping + + # +
+ +
+
+ + [View source] + +
+
+ + + +
+ + + diff --git a/api/0.2.2/DB/Any.html b/api/0.2.2/DB/Any.html new file mode 100644 index 0000000..11ac4dc --- /dev/null +++ b/api/0.2.2/DB/Any.html @@ -0,0 +1,200 @@ + + + + + + + + DB::Any - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + alias DB::Any + +

+ + + + + + + +

Alias Definition

+ Float32 | Float64 | Int32 | Int64 | Slice(UInt8) | String | Nil + + + + + + + + + + + + +

Defined in:

+ + + db.cr + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + diff --git a/api/0.2.2/DB/Connection.html b/api/0.2.2/DB/Connection.html new file mode 100644 index 0000000..c7edb21 --- /dev/null +++ b/api/0.2.2/DB/Connection.html @@ -0,0 +1,362 @@ + + + + + + + + DB::Connection - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + abstract class DB::Connection + +

+ + + + + + + +

Overview

+ +

Database driver implementors must subclass Connection.

+ +

Represents one active connection to a database.

+ +

Users should never instantiate a Connection manually. Use DB#open or Database#connection.

+ +

Refer to QueryMethods for documentation about querying the database through this connection.

+ +

Note to implementors

+ +

The connection must be initialized in #initialize and closed in #do_close.

+ +

Override #build_statement method in order to return a prepared Statement to allow querying. +See also Statement to define how the statements are executed.

+ +

If at any give moment the connection is lost a DB::ConnectionLost should be raised. This will +allow the connection pool to try to reconnect or use another connection if available.

+ + + + + +

Included Modules

+ + + + + + + + + + + +

Defined in:

+ + + db/connection.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + +

Instance methods inherited from module DB::QueryMethods

+ + + + exec(query, *args) + exec, + + + + query(query, *args)
query(query, *args, &block)
+ query
, + + + + query_all(query, *args, &block : ResultSet -> U) : Array(U)
query_all(query, *args, as types : Tuple)
query_all(query, *args, as type : Class)
+ query_all
, + + + + query_one(query, *args, &block : ResultSet -> U) : U
query_one(query, *args, as types : Tuple)
query_one(query, *args, as type : Class)
+ query_one
, + + + + query_one?(query, *args, &block : ResultSet -> U) : U?
query_one?(query, *args, as types : Tuple)
query_one?(query, *args, as type : Class)
+ query_one?
, + + + + scalar(query, *args) + scalar + + + + + + + + + + +

Instance methods inherited from module DB::Disposable

+ + + + close + close, + + + + closed? + closed? + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(database : Database) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ abstract + def build_statement(query) : Statement + + # +
+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/ConnectionLost.html b/api/0.2.2/DB/ConnectionLost.html new file mode 100644 index 0000000..3a9e004 --- /dev/null +++ b/api/0.2.2/DB/ConnectionLost.html @@ -0,0 +1,285 @@ + + + + + + + + DB::ConnectionLost - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::ConnectionLost + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/error.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(connection) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ + def connection : Connection + + # +
+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Database.html b/api/0.2.2/DB/Database.html new file mode 100644 index 0000000..44b1612 --- /dev/null +++ b/api/0.2.2/DB/Database.html @@ -0,0 +1,379 @@ + + + + + + + + DB::Database - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::Database + +

+ + + + + + + +

Overview

+ +

Acts as an entry point for database access. +Connections are managed by a pool. +The connection pool can be configured from URI parameters:

+ + + +

It should be created from DB module. See DB#open.

+ +

Refer to QueryMethods for documentation about querying the database.

+ + + + + +

Included Modules

+ + + + + + + + + + + +

Defined in:

+ + + db/database.cr + +
+ + + + + + + + +

Instance Method Summary

+ + + + + + +
+ + + +

Instance methods inherited from module DB::QueryMethods

+ + + + exec(query, *args) + exec, + + + + query(query, *args)
query(query, *args, &block)
+ query
, + + + + query_all(query, *args, &block : ResultSet -> U) : Array(U)
query_all(query, *args, as types : Tuple)
query_all(query, *args, as type : Class)
+ query_all
, + + + + query_one(query, *args, &block : ResultSet -> U) : U
query_one(query, *args, as types : Tuple)
query_one(query, *args, as type : Class)
+ query_one
, + + + + query_one?(query, *args, &block : ResultSet -> U) : U?
query_one?(query, *args, as types : Tuple)
query_one?(query, *args, as type : Class)
+ query_one?
, + + + + scalar(query, *args) + scalar + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +

Instance Method Detail

+ +
+
+ + def close + + # +
+ +

Closes all connection to the database.

+ +
+
+ + [View source] + +
+
+ +
+
+ + def setup_connection(&proc : Connection -> Nil) + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def uri : URI + + # +
+ +

Returns the uri with the connection settings to the database

+ +
+
+ + [View source] + +
+
+ +
+
+ + def using_connection(&block) + + # +
+ +

yields a connection from the pool +the connection is returned to the pool after +when the block ends

+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Disposable.html b/api/0.2.2/DB/Disposable.html new file mode 100644 index 0000000..85a1202 --- /dev/null +++ b/api/0.2.2/DB/Disposable.html @@ -0,0 +1,270 @@ + + + + + + + + DB::Disposable - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + module DB::Disposable + +

+ + + + + +

Overview

+ +

Generic module to encapsulate disposable db resources.

+ + + + + + + + + + + +

Direct including types

+ + + + + +

Defined in:

+ + + db/disposable.cr + +
+ + + + + + + + +

Instance Method Summary

+ + + + + + +
+ +
+ + + + +

Instance Method Detail

+ +
+
+ + def close + + # +
+ +

Closes this object.

+ +
+
+ + [View source] + +
+
+ +
+
+ + def closed? + + # +
+ +

Returns true if this object is closed. See #close.

+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Driver.html b/api/0.2.2/DB/Driver.html new file mode 100644 index 0000000..b187ed4 --- /dev/null +++ b/api/0.2.2/DB/Driver.html @@ -0,0 +1,288 @@ + + + + + + + + DB::Driver - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + abstract class DB::Driver + +

+ + + + + + + +

Overview

+ +

Database driver implementors must subclass Driver, +register with a driver_name using DB#register_driver and +override the factory method #build_connection.

+ +
require "db"
+
+class FakeDriver < Driver
+  def build_connection(db)
+    FakeConnection.new db
+  end
+end
+
+DB.register_driver "fake", FakeDriver
+ +

Access to this fake datbase will be available with

+ +
DB.open "fake://..." do |db|
+  # ... use db ...
+end
+ +

Refer to Connection, Statement and ResultSet for further +driver implementation instructions.

+ + + + + + + + + + + + + + +

Defined in:

+ + + db/driver.cr + +
+ + + + + + + + +

Instance Method Summary

+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +

Instance Method Detail

+ +
+
+ abstract + def build_connection(db : Database) : Connection + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def connection_pool_options(params : HTTP::Params) + + # +
+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Error.html b/api/0.2.2/DB/Error.html new file mode 100644 index 0000000..2bf41ef --- /dev/null +++ b/api/0.2.2/DB/Error.html @@ -0,0 +1,231 @@ + + + + + + + + DB::Error - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::Error + +

+ + + + + + + + + + + + + + + +

Direct Known Subclasses

+ + + + + + + +

Defined in:

+ + + db/error.cr + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + diff --git a/api/0.2.2/DB/ExecResult.html b/api/0.2.2/DB/ExecResult.html new file mode 100644 index 0000000..88b6d1f --- /dev/null +++ b/api/0.2.2/DB/ExecResult.html @@ -0,0 +1,320 @@ + + + + + + + + DB::ExecResult - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + struct DB::ExecResult + +

+ + + + + + + +

Overview

+ +

Result of a #exec statement.

+ + + + + + + + + + + + + + +

Defined in:

+ + + db.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(rows_affected : Int64, last_insert_id : Int64) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ + def clone + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def last_insert_id : Int64 + + # +
+ +
+
+ +
+
+ +
+
+ + def rows_affected : Int64 + + # +
+ +
+
+ +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Mappable.html b/api/0.2.2/DB/Mappable.html new file mode 100644 index 0000000..ec2979f --- /dev/null +++ b/api/0.2.2/DB/Mappable.html @@ -0,0 +1,201 @@ + + + + + + + + DB::Mappable - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + module DB::Mappable + +

+ + + + + +

Overview

+ +

Empty module used for marking a class as supporting DB:Mapping

+ + + + + + + + + + + + + + +

Defined in:

+ + + db/mapping.cr + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + diff --git a/api/0.2.2/DB/MappingException.html b/api/0.2.2/DB/MappingException.html new file mode 100644 index 0000000..19da0ae --- /dev/null +++ b/api/0.2.2/DB/MappingException.html @@ -0,0 +1,220 @@ + + + + + + + + DB::MappingException - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::MappingException + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/error.cr + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + diff --git a/api/0.2.2/DB/Pool.html b/api/0.2.2/DB/Pool.html new file mode 100644 index 0000000..8b0a16b --- /dev/null +++ b/api/0.2.2/DB/Pool.html @@ -0,0 +1,373 @@ + + + + + + + + DB::Pool(T) - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::Pool(T) + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/pool.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(initial_pool_size = 1, max_pool_size = 0, max_idle_pool_size = 1, checkout_timeout = 5.0, retry_attempts = 1, retry_delay = 0.2, &factory : -> T) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ + def checkout : T + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def checkout_some(candidates : Enumerable(WeakRef(T))) : ::Tuple(T, Bool) + + # +
+ +
selected, is_candidate = pool.checkout_some(candidates)
+ +

selected be a resource from the candidates list and is_candidate == true +or selected will be a new resource adn is_candidate == false

+ +
+
+ + [View source] + +
+
+ +
+
+ + def close : Nil + + # +
+ +

close all resources in the pool

+ +
+
+ + [View source] + +
+
+ +
+
+ + def release(resource : T) : Nil + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def retry(&block) + + # +
+ +

:nodoc: +Will retry the block if a ConnectionLost exception is thrown. +It will try to reuse all of the available connection right away, +but if a new connection is needed there is a retry_delay seconds delay.

+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Pool/TimeoutHelper.html b/api/0.2.2/DB/Pool/TimeoutHelper.html new file mode 100644 index 0000000..39198a0 --- /dev/null +++ b/api/0.2.2/DB/Pool/TimeoutHelper.html @@ -0,0 +1,313 @@ + + + + + + + + DB::Pool::TimeoutHelper - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::Pool::TimeoutHelper + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/pool.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(timeout : Float64) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ + def cancel + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def receive_select_action + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def start + + # +
+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/PoolRetryAttemptsExceeded.html b/api/0.2.2/DB/PoolRetryAttemptsExceeded.html new file mode 100644 index 0000000..ba7403b --- /dev/null +++ b/api/0.2.2/DB/PoolRetryAttemptsExceeded.html @@ -0,0 +1,227 @@ + + + + + + + + DB::PoolRetryAttemptsExceeded - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::PoolRetryAttemptsExceeded + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/error.cr + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + diff --git a/api/0.2.2/DB/PoolStatement.html b/api/0.2.2/DB/PoolStatement.html new file mode 100644 index 0000000..d9239e3 --- /dev/null +++ b/api/0.2.2/DB/PoolStatement.html @@ -0,0 +1,461 @@ + + + + + + + + DB::PoolStatement - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::PoolStatement + +

+ + + + + + + +

Overview

+ +

When a statement is to be executed in a DB that has a connection pool +a statement from the DB needs to be able to represent a statement in any +of the connections of the pool. Otherwise the user will need to deal with +actual connections in some point.

+ + + + + +

Included Modules

+ + + + + + + + + + + +

Defined in:

+ + + db/pool_statement.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + +

Instance methods inherited from module DB::StatementMethods

+ + + + exec(args : Array) : ExecResult
exec : ExecResult
exec(*args) : ExecResult
+ exec
, + + + + query(*args, &block)
query(args : Array) : ResultSet
query : ResultSet
query(*args) : ResultSet
+ query
, + + + + scalar(*args) + scalar + + + + + + + + + + +

Instance methods inherited from module DB::Disposable

+ + + + close + close, + + + + closed? + closed? + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(db : Database, query : String) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ + def exec(args : Array) : ExecResult + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def exec : ExecResult + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def exec(*args) : ExecResult + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query(args : Array) : ResultSet + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query : ResultSet + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query(*args) : ResultSet + + # +
+ + + +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/PoolTimeout.html b/api/0.2.2/DB/PoolTimeout.html new file mode 100644 index 0000000..79a6477 --- /dev/null +++ b/api/0.2.2/DB/PoolTimeout.html @@ -0,0 +1,227 @@ + + + + + + + + DB::PoolTimeout - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::PoolTimeout + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/error.cr + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + diff --git a/api/0.2.2/DB/QueryMethods.html b/api/0.2.2/DB/QueryMethods.html new file mode 100644 index 0000000..f76cd00 --- /dev/null +++ b/api/0.2.2/DB/QueryMethods.html @@ -0,0 +1,626 @@ + + + + + + + + DB::QueryMethods - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + module DB::QueryMethods + +

+ + + + + +

Overview

+ +

Methods to allow querying a database. +All methods accepts a query : String and a set arguments.

+ +

Three kind of statements can be performed:

+ +
  1. #exec waits no record response from the database. An ExecResult is returned.
  2. #scalar reads a single value of the response. A union of possible values is returned.
  3. #query returns a ResultSet that allows iteration over the rows in the response and column information.
+ +

Arguments can be passed by position

+ +
db.query("SELECT name FROM ... WHERE age > ?", age)
+ +

Convention of mapping how arguments are mapped to the query depends on each driver.

+ +

Including QueryMethods requires a prepare(query) : Statement method that is not expected +to be called directly.

+ + + + + + + + + + + +

Direct including types

+ + + + + +

Defined in:

+ + + db/query_methods.cr + +
+ + + + + + + + +

Instance Method Summary

+ + + + + + +
+ +
+ + + + +

Instance Method Detail

+ +
+
+ + def exec(query, *args) + + # +
+ +

Performs the #query and returns an ExecResult

+ +
+
+ + [View source] + +
+
+ +
+
+ + def query(query, *args) + + # +
+ +

Executes a query and returns a ResultSet with the results. +The ResultSet must be closed manually.

+ +
result = db.query "select name from contacts where id = ?", 10
+begin
+  if result.move_next
+    id = result.read(Int32)
+  end
+ensure
+  result.close
+end
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query(query, *args, &block) + + # +
+ +

Executes a query and yields a ResultSet with the results. +The ResultSet is closed automatically.

+ +
db.query("select name from contacts where age > ?", 18) do |rs|
+  rs.each do
+    name = rs.read(String)
+  end
+end
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_all(query, *args, &block : ResultSet -> U) : Array(U) + + # +
+ +

Executes a query and yield a ResultSet positioned at the beginning +of each row, returning an array of the values of the blocks.

+ +
names = db.query_all "select name from contacts", &.read(String)
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_all(query, *args, as types : Tuple) + + # +
+ +

Executes a query and returns an array where each row is +read as a tuple of the given types.

+ +
contacts = db.query_all "select name, age from contactas", as: {String, Int32}
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_all(query, *args, as type : Class) + + # +
+ +

Executes a query and returns an array where there first +column's value of each row is read as the given type.

+ +
names = db.query_all "select name from contactas", as: String
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_one(query, *args, &block : ResultSet -> U) : U + + # +
+ +

Executes a query that expects a single row and yields a ResultSet +positioned at that first row.

+ +

The given block must not invoke move_next on the yielded result set.

+ +

Raises DB::Error if there were no rows, or if there were more than one row.

+ +
name = db.query_one "select name from contacts where id = ?", 18, &.read(String)
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_one(query, *args, as types : Tuple) + + # +
+ +

Executes a query that expects a single row and returns it +as a tuple of the given types.

+ +

Raises DB::Error if there were no rows, or if there were more than one row.

+ +
db.query_one "select name, age from contacts where id = ?", 1, as: {String, Int32}
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_one(query, *args, as type : Class) + + # +
+ +

Executes a query that expects a single row +and returns the first column's value as the given type.

+ +

Raises DB::Error if there were no rows, or if there were more than one row.

+ +
db.query_one "select name from contacts where id = ?", 1, as: String
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_one?(query, *args, &block : ResultSet -> U) : U? + + # +
+ +

Executes a query that expects at most a single row and yields a ResultSet +positioned at that first row.

+ +

Returns nil, not invoking the block, if there were no rows.

+ +

Raises DB::Error if there were more than one row +(this ends up invoking the block once).

+ +
name = db.query_one? "select name from contacts where id = ?", 18, &.read(String)
+typeof(name) # => String | Nil
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_one?(query, *args, as types : Tuple) + + # +
+ +

Executes a query that expects a single row and returns it +as a tuple of the given types.

+ +

Returns nil if there were no rows.

+ +

Raises DB::Error if there were more than one row.

+ +
result = db.query_one? "select name, age from contacts where id = ?", 1, as: {String, Int32}
+typeof(result) # => Tuple(String, Int32) | Nil
+ +
+
+ + [View source] + +
+
+ +
+
+ + def query_one?(query, *args, as type : Class) + + # +
+ +

Executes a query that expects a single row +and returns the first column's value as the given type.

+ +

Returns nil if there were no rows.

+ +

Raises DB::Error if there were more than one row.

+ +
name = db.query_one? "select name from contacts where id = ?", 1, as: String
+typeof(name) # => String?
+ +
+
+ + [View source] + +
+
+ +
+
+ + def scalar(query, *args) + + # +
+ +

Performs the #query and returns a single scalar value +puts db.scalar("SELECT MAX(name)").as(String) # => (a String)

+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/ResultSet.html b/api/0.2.2/DB/ResultSet.html new file mode 100644 index 0000000..207e3c1 --- /dev/null +++ b/api/0.2.2/DB/ResultSet.html @@ -0,0 +1,550 @@ + + + + + + + + DB::ResultSet - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + abstract class DB::ResultSet + +

+ + + + + + + +

Overview

+ +

The response of a query performed on a Database.

+ +

See DB for a complete sample.

+ +

Each #read call consumes the result and moves to the next column. +Each column must be read in order. +At any moment a #move_next can be invoked, meaning to skip the +remaining, or even all the columns, in the current row. +Also it is not mandatory to consume the whole ResultSet, hence an iteration +through #each or #move_next can be stopped.

+ +

Note: depending on how the ResultSet was obtained it might be mandatory an +explicit call to #close. Check QueryMethods#query.

+ +

Note to implementors

+ +
  1. Override #move_next to move to the next row.
  2. Override #read returning the next value in the row.
  3. (Optional) Override #read(t) for some types t for which custom logic other than a simple cast is needed.
  4. Override #column_count, #column_name.
+ + + + + +

Included Modules

+ + + + + + + + + + + +

Defined in:

+ + + db/result_set.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + +

Instance methods inherited from module DB::Disposable

+ + + + close + close, + + + + closed? + closed? + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(statement : DB::Statement) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ abstract + def column_count : Int32 + + # +
+ +

Returns the number of columns in the result

+ +
+
+ + [View source] + +
+
+ +
+
+ abstract + def column_name(index : Int32) : String + + # +
+ +

Returns the name of the column in index 0-based position.

+ +
+
+ + [View source] + +
+
+ +
+
+ + def column_names + + # +
+ +

Returns the name of the columns.

+ +
+
+ + [View source] + +
+
+ +
+
+ + def each(&block) + + # +
+ +

Iterates over all the rows

+ +
+
+ + [View source] + +
+
+ +
+
+ + def each_column(&block) + + # +
+ +

Iterates over all the columns

+ +
+
+ + [View source] + +
+
+ +
+
+ abstract + def move_next : Bool + + # +
+ +

Move the next row in the result. +Return false if no more rows are available. +See #each

+ +
+
+ + [View source] + +
+
+ +
+
+ + def read(type : DB::Mappable.class) + + # +
+ +

Reads the next columns and maps them to a class

+ +
+
+ + [View source] + +
+
+ +
+
+ + def read(type : T.class) : T forall T + + # +
+ +

Reads the next column value as a type

+ +
+
+ + [View source] + +
+
+ +
+
+ abstract + def read + + # +
+ +

Reads the next column value

+ +
+
+ + [View source] + +
+
+ +
+
+ + def read(*types : Class) + + # +
+ +

Reads the next columns and returns a tuple of the values.

+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/Statement.html b/api/0.2.2/DB/Statement.html new file mode 100644 index 0000000..595fc91 --- /dev/null +++ b/api/0.2.2/DB/Statement.html @@ -0,0 +1,484 @@ + + + + + + + + DB::Statement - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + abstract class DB::Statement + +

+ + + + + + + +

Overview

+ +

Represents a prepared query in a Connection. +It should be created by QueryMethods.

+ +

Note to implementors

+ +
  1. Subclass Statements
  2. Statements are created from a custom driver Connection#prepare method.
  3. #perform_query executes a query that is expected to return a ResultSet
  4. #perform_exec executes a query that is expected to return an ExecResult
  5. #do_close is called to release the statement resources.
+ + + + + +

Included Modules

+ + + + + + + + + + + +

Defined in:

+ + + db/statement.cr + +
+ + + + + + +

Class Method Summary

+ + + + +

Instance Method Summary

+ + + + + + +
+ + + +

Instance methods inherited from module DB::StatementMethods

+ + + + exec(args : Array) : ExecResult
exec : ExecResult
exec(*args) : ExecResult
+ exec
, + + + + query(*args, &block)
query(args : Array) : ResultSet
query : ResultSet
query(*args) : ResultSet
+ query
, + + + + scalar(*args) + scalar + + + + + + + + + + +

Instance methods inherited from module DB::Disposable

+ + + + close + close, + + + + closed? + closed? + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Class Method Detail

+ +
+
+ + def self.new(connection : Connection) + + # +
+ +
+
+ + [View source] + +
+
+ + + + +

Instance Method Detail

+ +
+
+ + def exec(args : Array) + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def exec + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def exec(*args) + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query(args : Array) + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query(*args) + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def release_connection + + # +
+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/StatementMethods.html b/api/0.2.2/DB/StatementMethods.html new file mode 100644 index 0000000..fc78122 --- /dev/null +++ b/api/0.2.2/DB/StatementMethods.html @@ -0,0 +1,447 @@ + + + + + + + + DB::StatementMethods - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + module DB::StatementMethods + +

+ + + + + +

Overview

+ +

Common interface for connection based statements +and for connection pool statements.

+ + + + + +

Included Modules

+ + + + + + + + +

Direct including types

+ + + + + +

Defined in:

+ + + db/statement.cr + +
+ + + + + + + + +

Instance Method Summary

+ + + + + + +
+ + + +

Instance methods inherited from module DB::Disposable

+ + + + close + close, + + + + closed? + closed? + + + + + + + + +
+ + + + +

Instance Method Detail

+ +
+
+ abstract + def exec(args : Array) : ExecResult + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ abstract + def exec : ExecResult + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ abstract + def exec(*args) : ExecResult + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def query(*args, &block) + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ abstract + def query(args : Array) : ResultSet + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ abstract + def query : ResultSet + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ abstract + def query(*args) : ResultSet + + # +
+ + + +
+
+ + [View source] + +
+
+ +
+
+ + def scalar(*args) + + # +
+ + + +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/DB/StringKeyCache.html b/api/0.2.2/DB/StringKeyCache.html new file mode 100644 index 0000000..1920d36 --- /dev/null +++ b/api/0.2.2/DB/StringKeyCache.html @@ -0,0 +1,284 @@ + + + + + + + + DB::StringKeyCache(T) - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

+ + class DB::StringKeyCache(T) + +

+ + + + + + + + + + + + + + + + + + + + +

Defined in:

+ + + db/string_key_cache.cr + +
+ + + + + + + + +

Instance Method Summary

+ + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +

Instance Method Detail

+ +
+
+ + def clear + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def each_value(&block) + + # +
+ +
+
+ + [View source] + +
+
+ +
+
+ + def fetch(key : String, &block) : T + + # +
+ +
+
+ + [View source] + +
+
+ + + + + +
+ + + diff --git a/api/0.2.2/css/style.css b/api/0.2.2/css/style.css new file mode 100644 index 0000000..2994e37 --- /dev/null +++ b/api/0.2.2/css/style.css @@ -0,0 +1,432 @@ +html, body { + position: relative; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + overflow: hidden; +} + +body { + font-family: "Avenir", "Tahoma", "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + color: #333; +} + +a { + color: #263F6C; +} + +a:visited { + color: #112750; +} + +h1, h2, h3, h4, h5, h6 { + margin: 35px 0 25px; + color: #444444; +} + +h1.type-name { + color: #47266E; + margin: 20px 0 30px; + background-color: #F8F8F8; + padding: 10px 12px; + border: 1px solid #EBEBEB; + border-radius: 2px; +} + +h2 { + border-bottom: 1px solid #E6E6E6; + padding-bottom: 5px; +} + +#types-list, #main-content { + position: absolute; + top: 0; + bottom: 0; + overflow: auto; +} + +#types-list { + left: 0; + width: 20%; + background-color: #2E1052; + padding: 0 0 30px; + box-shadow: inset -3px 0 4px rgba(0,0,0,.35); +} + +#types-list #search-box { + padding: 8px 9px; +} + +#types-list input { + display: block; + box-sizing: border-box; + margin: 0; + padding: 5px; + font: inherit; + font-family: inherit; + line-height: 1.2; + width: 100%; + border: 0; + outline: 0; + border-radius: 2px; + box-shadow: 0px 3px 5px rgba(0,0,0,.25); + transition: box-shadow .12s; +} + +#types-list input:focus { + box-shadow: 0px 5px 6px rgba(0,0,0,.5); +} + +#types-list input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ + color: #C8C8C8; + font-size: 14px; + text-indent: 2px; +} + +#types-list input::-moz-placeholder { /* Firefox 19+ */ + color: #C8C8C8; + font-size: 14px; + text-indent: 2px; +} + +#types-list input:-ms-input-placeholder { /* IE 10+ */ + color: #C8C8C8; + font-size: 14px; + text-indent: 2px; +} + +#types-list input:-moz-placeholder { /* Firefox 18- */ + color: #C8C8C8; + font-size: 14px; + text-indent: 2px; +} + +#types-list ul { + margin: 0; + padding: 0; + list-style: none outside; +} + +#types-list li { + display: block; + position: relative; +} + +#types-list li.hide { + display: none; +} + +#types-list a { + display: block; + padding: 5px 15px 5px 30px; + text-decoration: none; + color: #F8F4FD; + transition: color .14s; +} + +#types-list a:focus { + outline: 1px solid #D1B7F1; +} + +#types-list .current > a, +#types-list a:hover { + color: #866BA6; +} + +#types-list li ul { + overflow: hidden; + height: 0; + max-height: 0; + transition: 1s ease-in-out; +} + + +#types-list li.parent { + padding-left: 30px; +} + +#types-list li.parent::before { + box-sizing: border-box; + content: "▼"; + display: block; + width: 30px; + height: 30px; + position: absolute; + top: 0; + left: 0; + text-align: center; + color: white; + font-size: 8px; + line-height: 30px; + transform: rotateZ(-90deg); + cursor: pointer; + transition: .2s linear; +} + + +#types-list li.parent > a { + padding-left: 0; +} + +#types-list li.parent.open::before { + transform: rotateZ(0); +} + +#types-list li.open > ul { + height: auto; + max-height: 1000em; +} + +#main-content { + padding: 0 30px 30px 30px; + left: 20%; + right: 0; +} + +.kind { + font-size: 60%; + color: #866BA6; +} + +.superclass-hierarchy { + margin: -15px 0 30px 0; + padding: 0; + list-style: none outside; + font-size: 80%; +} + +.superclass-hierarchy .superclass { + display: inline-block; + margin: 0 7px 0 0; + padding: 0; +} + +.superclass-hierarchy .superclass + .superclass::before { + content: "<"; + margin-right: 7px; +} + +.other-types-list li { + display: inline-block; +} + +.other-types-list, +.list-summary { + margin: 0 0 30px 0; + padding: 0; + list-style: none outside; +} + +.entry-const { + font-family: Consolas, 'Courier New', Courier, Monaco, monospace; +} + +.entry-summary { + padding-bottom: 4px; +} + +.superclass-hierarchy .superclass a, +.other-type a, +.entry-summary .signature { + padding: 4px 8px; + margin-bottom: 4px; + display: inline-block; + background-color: #f8f8f8; + color: #47266E; + border: 1px solid #f0f0f0; + text-decoration: none; + border-radius: 3px; + font-family: Consolas, 'Courier New', Courier, Monaco, monospace; + transition: background .15s, border-color .15s; +} + +.superclass-hierarchy .superclass a:hover, +.other-type a:hover, +.entry-summary .signature:hover { + background: #D5CAE3; + border-color: #624288; +} + +.entry-summary .summary { + padding-left: 32px; +} + +.entry-summary .summary p { + margin: 12px 0 16px; +} + +.entry-summary a { + text-decoration: none; +} + +.entry-detail { + padding: 30px 0; +} + +.entry-detail .signature { + position: relative; + padding: 5px 15px; + margin-bottom: 10px; + display: block; + border-radius: 5px; + background-color: #f8f8f8; + color: #47266E; + border: 1px solid #f0f0f0; + font-family: Consolas, 'Courier New', Courier, Monaco, monospace; + transition: .2s ease-in-out; +} + +.entry-detail:target .signature { + background-color: #D5CAE3; + border: 1px solid #624288; +} + +.entry-detail .signature .method-permalink { + position: absolute; + top: 0; + left: -35px; + padding: 5px 15px; + text-decoration: none; + font-weight: bold; + color: #624288; + opacity: .4; + transition: opacity .2s; +} + +.entry-detail .signature .method-permalink:hover { + opacity: 1; +} + +.entry-detail:target .signature .method-permalink { + opacity: 1; +} + +.methods-inherited { + padding-right: 10%; + line-height: 1.5em; +} + +.methods-inherited h3 { + margin-bottom: 4px; +} + +.methods-inherited a { + display: inline-block; + text-decoration: none; + color: #47266E; +} + +.methods-inherited a:hover { + text-decoration: underline; + color: #6C518B; +} + +.methods-inherited .tooltip>span { + background: #D5CAE3; + padding: 4px 8px; + border-radius: 3px; + margin: -4px -8px; +} + +.methods-inherited .tooltip * { + color: #47266E; +} + +pre { + padding: 10px 20px; + margin-top: 4px; + border-radius: 3px; + line-height: 1.45; + overflow: auto; + color: #333; + background: #fdfdfd; + font-size: 14px; + border: 1px solid #eee; +} + +code { + font-family: Consolas, 'Courier New', Courier, Monaco, monospace; +} + +span.flag { + padding: 2px 4px 1px; + border-radius: 3px; + margin-right: 3px; + font-size: 11px; + border: 1px solid transparent; +} + +span.flag.orange { + background-color: #EE8737; + color: #FCEBDD; + border-color: #EB7317; +} + +span.flag.yellow { + background-color: #E4B91C; + color: #FCF8E8; + border-color: #B69115; +} + +span.flag.green { + background-color: #469C14; + color: #E2F9D3; + border-color: #34700E; +} + +span.flag.red { + background-color: #BF1919; + color: #F9ECEC; + border-color: #822C2C; +} + +span.flag.purple { + background-color: #2E1052; + color: #ECE1F9; + border-color: #1F0B37; +} + +.tooltip>span { + position: absolute; + opacity: 0; + display: none; + pointer-events: none; +} + +.tooltip:hover>span { + display: inline-block; + opacity: 1; +} + +.c { + color: #969896; +} + +.n { + color: #0086b3; +} + +.t { + color: #0086b3; +} + +.s { + color: #183691; +} + +.i { + color: #7f5030; +} + +.k { + color: #a71d5d; +} + +.o { + color: #a71d5d; +} + +.m { + color: #795da3; +} diff --git a/api/0.2.2/index.html b/api/0.2.2/index.html new file mode 100644 index 0000000..f2a94c9 --- /dev/null +++ b/api/0.2.2/index.html @@ -0,0 +1,205 @@ + + + + + + + + README - github.com/crystal-lang/crystal-db + + + +
+ + + + + + +
+ +
+

Build Status

+ +

crystal-db

+ +

Common db api for crystal. You will need to a specific driver to access a database.

+ + + +

Installation

+ +

Add this to your application's shard.yml:

+ +
dependencies:
+  db:
+    github: crystal-lang/crystal-db
+ +

Usage

+ +

Since this is an abstract db api, it's usage is through a concrete database driver.

+ +
require "db"
+require "sqlite3"
+
+DB.open "sqlite3:./file.db" do |db|
+  db.exec "create table contacts (name string, age integer)"
+  db.exec "insert into contacts values (?, ?)", "John Doe", 30
+
+  args = [] of DB::Any
+  args << "Sarah"
+  args << 33
+  db.exec "insert into contacts values (?, ?)", args
+
+  puts "max age:"
+  puts db.scalar "select max(age) from contacts" # => 33
+
+  puts "contacts:"
+  db.query "select name, age from contacts order by age desc" do |rs|
+    puts "#{rs.column_name(0)} (#{rs.column_name(1)})"
+    # => name (age)
+    rs.each do
+      puts "#{rs.read(String)} (#{rs.read(Int32)})"
+      # => Sarah (33)
+      # => John Doe (30)
+    end
+  end
+end
+ +

Roadmap

+ +

Issues not yet addressed

+ + + +

Contributing

+ +
  1. Fork it ( https://github.com/crystal-lang/crystal-db/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request
+ +

Contributors

+ + +
+ + diff --git a/api/0.2.2/js/doc.js b/api/0.2.2/js/doc.js new file mode 100644 index 0000000..b62d682 --- /dev/null +++ b/api/0.2.2/js/doc.js @@ -0,0 +1,108 @@ +document.addEventListener('DOMContentLoaded', function() { + var sessionStorage = window.sessionStorage; + if(!sessionStorage) { + sessionStorage = { + setItem: function() {}, + getItem: function() {}, + removeItem: function() {} + }; + } + + var repositoryName = document.getElementById('repository-name').getAttribute('content'); + var typesList = document.getElementById('types-list'); + var searchInput = document.getElementById('search-input'); + var parents = document.querySelectorAll('#types-list li.parent'); + + for(var i = 0; i < parents.length; i++) { + var _parent = parents[i]; + _parent.addEventListener('click', function(e) { + e.stopPropagation(); + + if(e.target.tagName.toLowerCase() == 'li') { + if(e.target.className.match(/open/)) { + sessionStorage.removeItem(e.target.getAttribute('data-id')); + e.target.className = e.target.className.replace(/ +open/g, ''); + } else { + sessionStorage.setItem(e.target.getAttribute('data-id'), '1'); + if(e.target.className.indexOf('open') == -1) { + e.target.className += ' open'; + } + } + } + }); + + if(sessionStorage.getItem(_parent.getAttribute('data-id')) == '1') { + _parent.className += ' open'; + } + }; + + var childMatch = function(type, regexp){ + var types = type.querySelectorAll("ul li"); + for (var j = 0; j < types.length; j ++) { + var t = types[j]; + if(regexp.exec(t.getAttribute('data-name'))){ return true; }; + }; + return false; + }; + + var searchTimeout; + var performSearch = function() { + clearTimeout(searchTimeout); + searchTimeout = setTimeout(function() { + var text = searchInput.value; + var types = document.querySelectorAll('#types-list li'); + var words = text.toLowerCase().split(/\s+/).filter(function(word) { + return word.length > 0; + }); + var regexp = new RegExp(words.join('|')); + + for(var i = 0; i < types.length; i++) { + var type = types[i]; + if(words.length == 0 || regexp.exec(type.getAttribute('data-name')) || childMatch(type, regexp)) { + type.className = type.className.replace(/ +hide/g, ''); + var is_parent = new RegExp("parent").exec(type.className); + var is_not_opened = !(new RegExp("open").exec(type.className)); + if(childMatch(type,regexp) && is_parent && is_not_opened){ + type.className += " open"; + }; + } else { + if(type.className.indexOf('hide') == -1) { + type.className += ' hide'; + }; + }; + if(words.length == 0){ + type.className = type.className.replace(/ +open/g, ''); + }; + } + }, 200); + }; + if (searchInput.value.length > 0) { + performSearch(); + } + searchInput.addEventListener('keyup', performSearch); + searchInput.addEventListener('input', performSearch); + + typesList.onscroll = function() { + var y = typesList.scrollTop; + sessionStorage.setItem(repositoryName + '::types-list:scrollTop', y); + }; + + var initialY = parseInt(sessionStorage.getItem(repositoryName + '::types-list:scrollTop') + "", 10); + if(initialY > 0) { + typesList.scrollTop = initialY; + } + + var scrollToEntryFromLocationHash = function() { + var hash = window.location.hash; + if (hash) { + var targetAnchor = unescape(hash.substr(1)); + var targetEl = document.querySelectorAll('.entry-detail[id="' + targetAnchor + '"]'); + + if (targetEl && targetEl.length > 0) { + targetEl[0].offsetParent.scrollTop = targetEl[0].offsetTop; + } + } + }; + window.addEventListener("hashchange", scrollToEntryFromLocationHash, false); + scrollToEntryFromLocationHash(); +});